Created
January 7, 2017 14:06
-
-
Save sehugg/6218e965ddfcf2445011c44b8643fe36 to your computer and use it in GitHub Desktop.
An Apple ][ emulator in 8086 assembler
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name cpu | |
.model large | |
EXTRN _rwts | |
.data | |
EXTRN _memseg:DWORD | |
.code | |
; *** EQUATES | |
acc equ cl | |
x equ dl | |
y equ dh | |
flags equ ch | |
@no equ cycl | |
overflow equ 64 | |
breakflag equ 16 | |
decmode equ 8 | |
irqdisable equ 4 | |
unusedflag equ 32 | |
allflags equ not (1+2+128) | |
orflags equ unusedflag+breakflag | |
IOmap equ byte ptr ds:0c700h | |
opcodes equ word ptr ds:0c400h | |
RESvector equ word ptr ds:0fffch | |
IRQvector equ word ptr ds:0fffeh | |
keyflag equ byte ptr ds:0c05fh | |
int9 equ 9*4 | |
vidout equ word ptr ds:0c050h ;address of I/O routine | |
vidmix equ byte ptr ds:0c052h ;bit 0: OFF=TEXT,ON=GR | |
;bit 1: OFF=MIX,ON=NOMIX | |
;bit 2: OFF=PAGE0,ON=PAGE1 | |
;bit 3: OFF=LORES,ON=HIRES | |
; *** VARIABLES | |
old_int3 dd ? | |
old_int9 dd ? | |
dsseg dw ? | |
esseg dw ? | |
oldsp dw ? | |
modenow db ? | |
; ----- MACROS ----- | |
; CYCLE - process next instruction | |
; | |
; NOTE: if operand is zero page or last instruction's code < 80h, bh = 0. | |
Cycle macro isbh0 | |
IFNDEF GOSLOW | |
lodsb | |
mov bl,al | |
IFB <isbh0> | |
mov bh,0 | |
ENDIF | |
shl bx,1 | |
jmp opcodes[bx] | |
ELSE | |
jmp cycl | |
ENDIF | |
endm | |
@maketables: | |
push ds | |
push es | |
mov ax,ds | |
mov es,ax | |
mov ax,cs | |
mov ds,ax | |
mov si,offset opcodes_org | |
mov di,offset opcodes | |
mov cx,256 | |
rep movsw | |
xor ax,ax | |
mov di,offset IOmap | |
mov cx,0c0h/2 | |
rep stosw | |
dec ax | |
mov cx,040h/2 | |
rep stosw | |
xor bx,bx | |
mov al,64 | |
mov cx,64 | |
@tblp2: | |
mov byte ptr cs:textchar[bx],al | |
mov byte ptr cs:textchar[bx+128],al | |
mov byte ptr cs:textchar[bx+256],al | |
mov byte ptr cs:textchar[bx+1],70h | |
mov byte ptr cs:textchar[bx+129],87h | |
mov byte ptr cs:textchar[bx+257],07h | |
add bx,2 | |
inc al | |
cmp al,96 | |
jnz @tbsk1 | |
mov al,32 | |
@tbsk1: | |
loop @tblp2 | |
mov bx,160*2 | |
mov al,32 | |
mov cx,96 | |
@tblp3: | |
mov byte ptr cs:textchar[bx],al | |
mov byte ptr cs:textchar[bx+1],07h | |
add bx,2 | |
inc al | |
loop @tblp3 | |
mov byte ptr cs:textchar[192],0dbh | |
pop es | |
pop ds | |
ret | |
; SCREEN-SETTING ROUTINES | |
map_gr_page: | |
mov ax,ds | |
mov es,ax | |
mov di,offset IOmap+4 | |
xor ax,ax | |
mov cx,4 | |
rep stosw | |
dec ax | |
test vidmix,2 ;see if mixed mode | |
jnz @mixmap | |
mov bl,vidmix | |
and bx,4 | |
add bl,6 | |
mov word ptr IOmap[bx],ax | |
@mixmap: | |
ret | |
map_text_page: | |
mov ax,ds | |
mov es,ax | |
xor ax,ax | |
mov di,offset IOmap+20h | |
mov cx,20h | |
rep stosw | |
test vidmix,4 ;which page? | |
jnz mappg1 ;page 2 | |
dec ax | |
mappg1: | |
mov di,offset IOmap+4h | |
stosw | |
stosw | |
not ax | |
stosw | |
stosw | |
ret | |
changemode: | |
mov bx,0b800h | |
cmp al,12 | |
jb notegamode | |
mov bh,0a0h | |
notegamode: | |
mov es,bx | |
mov esseg,bx | |
cmp al,modenow | |
je nochngmode | |
mov modenow,al | |
mov ah,0 | |
or al,128 | |
int 10h | |
nochngmode: | |
ret | |
flip_page: | |
test vidmix,1 | |
jz draw_screen | |
test vidmix,8 | |
jz draw_screen | |
push ax | |
push dx | |
mov dx,3d4h | |
mov ax,0Ch | |
test vidmix,4 | |
jz flippg1 | |
mov ah,20h | |
flippg1: | |
out dx,ax | |
pop dx | |
pop ax | |
ret | |
draw_screen: | |
push ax | |
push bx | |
push cx | |
push dx | |
push si | |
push di | |
mov al,vidmix | |
test al,1 | |
jnz drawgr | |
jmp drawtext | |
drawgr: | |
test al,8 | |
jz drawlores | |
jmp drawhires | |
drpgr_end: | |
mov di,40*24*8 | |
mov cx,20*8 | |
xor ax,ax | |
rep stosw | |
test vidmix,2 | |
jnz drpg_end | |
call @drawtextbot | |
drpg_end: | |
pop di | |
pop si | |
pop dx | |
pop cx | |
pop bx | |
pop ax | |
ret | |
drawhires: | |
call map_gr_page | |
mov si,2000h | |
mov di,offset IOmap+20h | |
mov ax,0ffffh | |
; test vidmix,4 | |
; jz @hipg1 | |
; mov si,4000h | |
; inc ax | |
@hipg1: | |
mov cx,10h | |
rep stosw | |
; not ax | |
mov cx,10h | |
rep stosw | |
mov al,13 | |
call changemode | |
call flip_page | |
mov vidout,offset hiresvid | |
mov cx,3ff8h | |
@lptxt2: | |
mov bx,si | |
call vidout | |
inc si | |
loop @lptxt2 | |
mov di,40*24*8+2000h | |
mov cx,20*8 | |
xor ax,ax | |
rep stosw | |
jmp drpgr_end | |
drawlores: | |
mov dx,3ceh | |
mov ax,205h | |
out dx,ax | |
mov ax,0ff08h | |
out dx,ax | |
mov al,13 | |
call changemode | |
mov dx,3d4h | |
mov ax,0ch | |
out dx,ax | |
mov vidout,offset loresvid | |
call @drawtextpage | |
jmp drpgr_end | |
drawtext: | |
mov al,0 | |
call changemode | |
mov ah,2 | |
mov bh,0 | |
mov dx,0ffffh | |
int 10h | |
mov vidout,offset textvid | |
call @drawtextpage | |
mov di,80*24 | |
mov cx,40 | |
xor ax,ax | |
rep stosw | |
jmp drpg_end | |
@drawtextpage: | |
push es | |
call map_text_page | |
pop es | |
mov cx,400h | |
mov bh,4 | |
test vidmix,4 | |
je settpag | |
mov bh,8 | |
settpag: | |
mov bl,0 | |
mov si,bx | |
@lptxt: mov bx,si | |
call vidout | |
inc si | |
loop @lptxt | |
ret | |
@drawtextbot: | |
test vidmix,8 | |
jz splegu | |
push es | |
call map_gr_page | |
pop es | |
splegu: | |
mov bx,650h | |
test vidmix,4 | |
je settpag1 | |
add bh,4 | |
settpag1: | |
mov si,bx | |
REPT 4 | |
LOCAL @lptxt1 | |
mov cx,28h | |
@lptxt1: | |
mov bx,si | |
call loresvid | |
inc si | |
loop @lptxt1 | |
add si,80h-28h | |
ENDM | |
ret | |
; INT9RTN - interrupt when key pressed | |
int3rtn: | |
push bp | |
mov bp,sp | |
push bx | |
mov bx,[bp+4] ;prev CS | |
cmp bx,@code | |
jne notrap | |
push ds | |
mov ds,bx | |
mov bx,[bp+2] ;prev IP | |
cmp [bx],0ffa7h ;instruction at which to break | |
mov es:[2],bx | |
cmp [bx+2],offset opcodes | |
je trapper | |
notrap2: | |
pop ds | |
notrap: | |
pop bx | |
pop bp | |
iret | |
trapper: | |
pop ds | |
pop bx | |
and [bp+6],not 100h | |
pop bp | |
add sp,4 | |
popf | |
jmp getkeyflag | |
quitkey: | |
mov keyflag,ah | |
push di | |
push dx | |
mov di,offset old_int3 | |
mov dx,offset int3rtn | |
mov al,1 | |
call @setintnum | |
pop dx | |
pop di | |
pop ax | |
push bp | |
mov bp,sp | |
or word ptr [bp+6],100h ;set trap flag | |
pop bp | |
iret | |
int9rtn: | |
push ax | |
pushf | |
call old_int9 | |
mov ah,1 | |
int 16h | |
jz int_nokey | |
mov ah,0 | |
int 16h | |
or al,al | |
jne noextkey | |
cmp ah,10h ;Alt-Q | |
je quitkey | |
cmp ah,13h | |
je quitkey | |
jmp int_nokey | |
noextkey: | |
push es | |
push cx | |
push di | |
mov es,[dsseg] | |
or al,80h | |
mov di,0c000h | |
mov cx,16 | |
rep stosb | |
pop di | |
pop cx | |
pop es | |
int_nokey: | |
pop ax | |
iret | |
@setintnum: | |
push bx | |
push es | |
push ds | |
mov ah,35h | |
int 21h | |
mov word ptr cs:[di],bx | |
mov word ptr cs:[di+2],es | |
mov bx,cs | |
mov ds,bx | |
mov ah,25h | |
int 21h | |
pop ds | |
pop es | |
pop bx | |
ret | |
@setinterrupts: | |
mov di,offset old_int9 | |
mov dx,offset int9rtn | |
mov al,9 | |
call @setintnum | |
ret | |
@clearinterrupts: | |
mov di,ds | |
lds dx,old_int9 | |
mov ax,2509h | |
int 21h | |
mov ds,di | |
ret | |
; | |
_process PROC | |
PUBLIC _process | |
push bp | |
mov bp,sp | |
push ds | |
mov oldsp,sp | |
reset: | |
mov ds,word ptr [_memseg+2] | |
mov dsseg,ds | |
mov modenow,255 | |
call @setinterrupts | |
call @maketables | |
doreset: | |
call draw_screen | |
xor ax,ax | |
xor cx,cx | |
xor dx,dx ;set regs to zero | |
mov flags,orflags | |
clc | |
cld | |
mov bp,01FFh ;set stack ptr to $ff | |
mov si,RESvector ;reset program counter | |
cycl: | |
lodsb | |
mov bl,al | |
mov bh,0 | |
shl bx,1 | |
jmp opcodes[bx] | |
getkeyflag: ;special key pressed | |
mov al,keyflag | |
mov keyflag,0 | |
cmp al,10h | |
je endprocess ;Alt-Q | |
cmp al,13h | |
je doreset | |
jmp cycl | |
; CHKRTN - check locations for store instructions | |
endprocess: | |
call @clearinterrupts | |
mov ax,2 | |
int 10h | |
mov sp,oldsp | |
pop ds | |
pop bp | |
ret | |
_process endp | |
; *** INDEX FOR OPCODES | |
opcodes_org: | |
dw @0,@1,@no,@no,@no,@5,@6,@no,@8,@9,@a,@no,@no,@d,@e,@no | |
dw @10,@11,@no,@no,@no,@15,@16,@no,@18,@19,@no,@no,@no,@1d,@1e,@no | |
dw @20,@21,@no,@no,@24,@25,@26,@no,@28,@29,@2a,@no,@2c,@2d,@2e,@no | |
dw @30,@31,@no,@no,@no,@35,@36,@37,@38,@39,@no,@no,@no,@3d,@3e,@no | |
dw @40,@41,@no,@no,@no,@45,@46,@no,@48,@49,@4a,@no,@4c,@4d,@4e,@no | |
dw @50,@51,@no,@no,@no,@55,@56,@no,@58,@59,@no,@no,@no,@5d,@5e,@no | |
dw @60,@61,@no,@no,@no,@65,@66,@no,@68,@69,@6a,@no,@6c,@6d,@6e,@no | |
dw @70,@71,@no,@no,@no,@75,@76,@no,@78,@79,@no,@no,@no,@7d,@7e,@no | |
dw @no,@81,@no,@no,@84,@85,@86,@no,@88,@no,@8a,@no,@8c,@8d,@8e,@no | |
dw @90,@91,@no,@no,@94,@95,@96,@no,@98,@99,@9a,@no,@no,@9d,@no,@no | |
dw @a0,@a1,@a2,@no,@a4,@a5,@a6,@no,@a8,@a9,@aa,@no,@ac,@ad,@ae,@no | |
dw @b0,@b1,@no,@no,@b4,@b5,@b6,@no,@b8,@b9,@ba,@no,@bc,@bd,@be,@no | |
dw @c0,@c1,@no,@no,@c4,@c5,@c6,@no,@c8,@c9,@ca,@no,@cc,@cd,@ce,@no | |
dw @d0,@d1,@no,@no,@no,@d5,@d6,@no,@d8,@d9,@no,@no,@no,@dd,@de,@no | |
dw @e0,@e1,@no,@no,@e4,@e5,@e6,@no,@e8,@e9,@ea,@no,@ec,@ed,@ee,@no | |
dw @f0,@f1,@no,@no,@no,@f5,@f6,@no,@f8,@f9,@no,@no,@no,@fd,@fe,@no | |
phptbl db 0,2,128,2+128,1,1+2,1+128,1+2+128 | |
plptbl db 0,128,1,1+128,64,64+128,64+1,64+128+1 | |
; CHKRTN - check locations for store instructions | |
chkrtn macro oper | |
LOCAL @fish,@IO,@stor,nofish | |
IFNB <oper> | |
mov al,bh | |
mov di,ax | |
and di,0ffh | |
test IOmap[di],255 | |
jnz @fish | |
oper | |
Cycle | |
@fish: cmp bh,0c0h | |
je @IO | |
ja nofish | |
oper | |
call vidout | |
jmp near ptr cycl | |
@IO: call near ptr doIO | |
nofish: jmp near ptr cycl | |
ENDIF | |
endm | |
ifio macro oper,dojmp | |
LOCAL @fesh,@lohd | |
cmp bh,0c0h | |
je @fesh | |
@lohd: oper | |
;IFB <dojmp> | |
Cycle | |
;ELSE | |
; jmp cycl | |
;ENDIF | |
@fesh: call near ptr doIO | |
jmp @lohd | |
endm | |
; ADDRESSING MODES - | |
getzp macro isbh0 ;lda aa | |
lodsb | |
IFB <isbh0> | |
mov bh,0 | |
ENDIF | |
mov bl,al | |
endm | |
getzpx macro isbh0 ;lda aa,x | |
lodsb | |
add al,x | |
IFB <isbh0> | |
mov bh,0 | |
ENDIF | |
mov bl,al | |
endm | |
getzpy macro isbh0 ;lda aa,y | |
lodsb | |
add al,y | |
IFB <isbh0> | |
mov bh,0 | |
ENDIF | |
mov bl,al | |
endm | |
getabs macro oper ;lda aaaa | |
mov bx,[si] | |
add si,2 | |
chkrtn <oper> | |
endm | |
getabsx macro oper ;lda aaaa,x | |
mov bx,[si] | |
add si,2 | |
add bl,x | |
adc bh,0 | |
chkrtn <oper> | |
endm | |
getabsy macro oper ;lda aaaa,y | |
mov bx,[si] | |
add si,2 | |
add bl,y | |
adc bh,0 | |
chkrtn <oper> | |
endm | |
getindx macro oper ;lda (aa,x) | |
mov bh,0 | |
mov bl,[si] | |
inc si | |
add bl,x | |
mov bx,[bx] | |
chkrtn <oper> | |
endm | |
getindy macro oper ;lda (aa),y | |
mov bh,0 | |
mov bl,[si] | |
inc si | |
mov bx,[bx] | |
add bl,y | |
adc bh,0 | |
chkrtn <oper> | |
endm | |
; MISC. MACROS - | |
movor macro z ;move [bx] to z, compare | |
mov z,[bx] | |
sahf | |
inc z | |
dec z | |
lahf | |
endm | |
pushon macro z ;push z on stack | |
mov bx,bp | |
mov byte ptr [bx],z | |
dec bl | |
mov bp,bx | |
endm | |
pulloff macro z ;pull z off stack | |
mov bx,bp | |
inc bl | |
mov bp,bx | |
mov z,byte ptr [bx] | |
endm | |
setovf macro ;set overflow flag | |
LOCAL @oo1 | |
and flags,not overflow | |
jno @oo1 | |
or flags,overflow | |
@oo1: | |
endm | |
scf macro op,z,cycexit ;save carry flag | |
LOCAL @scf1 | |
sahf | |
jnc @scf1 | |
op acc,z | |
stc | |
lahf | |
jmp cycexit | |
@scf1: op acc,z | |
lahf | |
jmp cycexit | |
endm | |
lodreg macro reg ;load register | |
mov reg,word ptr [si] | |
add si,2 | |
endm | |
; *** AND NOW THE INSTRUCTIONS | |
; *** IN ALPHABETICAL ORDER | |
@69: ; adc #aa | |
lodsb | |
sahf | |
adc acc,al | |
lahf | |
setovf | |
Cycle | |
@65: ; adc aa | |
getzp bh0 | |
sahf | |
adc acc,[bx] | |
lahf | |
setovf | |
Cycle | |
@75: ; adc aa,x | |
getzpx bh0 | |
sahf | |
adc acc,[bx] | |
lahf | |
setovf | |
jmp cycl | |
@6d: ; adc aaaa | |
getabs | |
sahf | |
adc acc,[bx] | |
lahf | |
setovf | |
Cycle | |
@7d: ; adc aaaa,x | |
getabsx | |
sahf | |
adc acc,[bx] | |
lahf | |
setovf | |
jmp cycl | |
@79: ; adc aaaa,y | |
getabsy | |
sahf | |
adc acc,[bx] | |
lahf | |
setovf | |
jmp cycl | |
@61: ; adc (aa,x) | |
getindx | |
sahf | |
adc acc,[bx] | |
lahf | |
setovf | |
jmp cycl | |
@71: ; adc (aa),y | |
getindy | |
sahf | |
adc acc,[bx] | |
lahf | |
setovf | |
Cycle | |
@29: ; and #aa | |
lodsb | |
scf and,al,cycl | |
@25: ; and aa | |
getzp bh0 | |
scf and,[bx],cycl | |
@35: ; and aa,x | |
getzpx bh0 | |
scf and,[bx],cycl | |
@2d: ; and aaaa | |
getabs | |
scf and,[bx],cycl | |
@3d: ; and aaaa,x | |
getabsx | |
scf and,[bx],cycl | |
@39: ; and aaaa,y | |
getabsy | |
scf and,[bx],cycl | |
@21: ; and (aa,x) | |
getindx | |
scf and,[bx],cycl | |
@31: ; and (aa),y | |
getindy | |
scf and,[bx],cycl | |
@a: ; asl a | |
sahf | |
shl acc,1 | |
lahf | |
Cycle bh0 | |
@6: ; asl aa | |
getzp bh0 | |
sahf | |
shl byte ptr [bx],1 | |
lahf | |
Cycle bh0 | |
@16: ; asl aa,x | |
getzpx bh0 | |
sahf | |
shl byte ptr [bx],1 | |
lahf | |
jmp cycl | |
@e: ; asl aaaa | |
getabs | |
sahf | |
shl byte ptr [bx],1 | |
lahf | |
Cycle | |
@1e: ; asl aaaa,x | |
getabsx | |
sahf | |
shl byte ptr [bx],1 | |
lahf | |
jmp cycl | |
branch macro z,isbh0 ;if z, branch | |
LOCAL nobranch | |
lodsb | |
z nobranch | |
mov bl,ah | |
cbw | |
add si,ax | |
mov ah,bl | |
nobranch: | |
Cycle <isbh0> | |
endm | |
@90: ; bcc | |
sahf | |
branch jc | |
@b0: ; bcs | |
sahf | |
branch jnc | |
@f0: ; beq | |
sahf | |
branch jne | |
@30: ; bmi | |
sahf | |
branch jns,bh0 | |
@d0: ; bne | |
sahf | |
branch je | |
@10: ; bpl | |
sahf | |
branch js,bh0 | |
@50: ; bvc | |
test flags,overflow | |
branch jnz,bh0 | |
@70: ; bvs | |
test flags,overflow | |
branch jz,bh0 | |
bitop macro | |
LOCAL @bit_1,@bit_2,@bit_3 | |
mov al,[bx] | |
and ah,not (040h+080h) | |
and flags,not overflow | |
test al,64 | |
jz @bit_1 | |
or flags,overflow ;overflag flag | |
@bit_1: or al,al | |
jns @bit_3 | |
or ah,080h ;set sign flag | |
@bit_3: test acc,al | |
jnz @bit_2 | |
or ah,040h ;set zero flag | |
@bit_2: | |
endm | |
@24: ; bit aa | |
getzp bh0 | |
bitop | |
Cycle | |
@2c: ; bit aaaa | |
getabs | |
ifio <bitop>,<jump> | |
PURGE bitop | |
@0: ; brk | |
push cx | |
mov cx,si | |
add si,2 | |
pushon ch | |
pushon cl | |
pop cx | |
mov bl,ah | |
rol bl,1 | |
rol bl,1 | |
and bx,7 | |
mov al,phptbl[bx] | |
or flags,breakflag | |
or al,flags | |
pushon al | |
mov si,[IRQvector] | |
jmp cycl | |
@18: ; clc | |
and ah,254 | |
Cycle bh0 | |
@d8: ; cld | |
and flags,not decmode | |
jmp cycl | |
@58: ; cli | |
and flags,not irqdisable | |
jmp cycl | |
@b8: ; clv | |
and flags,not overflow | |
jmp cycl | |
compar macro reg,mem | |
sahf | |
cmp reg,mem | |
cmc | |
lahf | |
endm | |
@c9: ; cmp #aa | |
lodsb | |
compar acc,al | |
Cycle | |
@c5: ; cmp aa | |
getzp | |
compar acc,[bx] | |
Cycle bh0 | |
@d5: ; cmp aa,x | |
getzpx | |
compar acc,[bx] | |
cmc | |
jmp cycl | |
@cd: ; cmp aaaa | |
getabs | |
compar acc,[bx] | |
Cycle | |
@dd: ; cmp aaaa,x | |
getabsx | |
compar acc,[bx] | |
jmp cycl | |
@d9: ; cmp aaaa,y | |
getabsy | |
compar acc,[bx] | |
jmp cycl | |
@c1: ; cmp (aa,x) | |
getindx | |
compar acc,[bx] | |
jmp cycl | |
@d1: ; cmp (aa),y | |
getindy | |
compar acc,[bx] | |
Cycle | |
@e0: ; cpx #aa | |
lodsb | |
compar x,al | |
Cycle | |
@e4: ; cpx aa | |
getzp | |
compar x,[bx] | |
Cycle bh0 | |
@ec: ; cpx aaaa | |
getabs | |
compar x,[bx] | |
Cycle | |
@c0: ; cpy #aa | |
lodsb | |
compar y,al | |
Cycle | |
@c4: ; cpy aa | |
getzp | |
compar y,[bx] | |
Cycle bh0 | |
@cc: ; cpy aaaa | |
getabs | |
compar y,[bx] | |
Cycle | |
@c6: ; dec aa | |
getzp | |
sahf | |
dec byte ptr [bx] | |
lahf | |
Cycle bh0 | |
@d6: ; dec aa,x | |
getzpx | |
sahf | |
dec byte ptr [bx] | |
lahf | |
jmp cycl | |
@ce: ; dec aaaa | |
getabs | |
sahf | |
dec byte ptr [bx] | |
lahf | |
Cycle | |
@de: ; dec aaaa,x | |
getabsx | |
sahf | |
dec byte ptr [bx] | |
lahf | |
jmp cycl | |
@ca: ; dex | |
sahf | |
dec x | |
lahf | |
Cycle | |
@88: ; dey | |
sahf | |
dec y | |
lahf | |
Cycle | |
@49: ; eor #aa | |
lodsb | |
scf xor,al,cycl | |
@45: ; eor aa | |
getzp bh0 | |
scf xor,[bx],cycl | |
@55: ; eor aa,x | |
getzpx bh0 | |
scf xor,[bx],cycl | |
@4d: ; eor aaaa | |
getabs | |
scf xor,[bx],cycl | |
@5d: ; eor aaaa,x | |
getabsx | |
scf xor,[bx],cycl | |
@59: ; eor aaaa,y | |
getabsy | |
scf xor,[bx],cycl | |
@41: ; eor (aa,x) | |
getindx | |
scf xor,[bx],cycl | |
@51: ; eor (aa),y | |
getindy | |
scf xor,[bx],cycl | |
@e6: ; inc aa | |
getzp | |
sahf | |
inc byte ptr [bx] | |
lahf | |
Cycle bh0 | |
@f6: ; inc aa,x | |
getzpx | |
sahf | |
inc byte ptr [bx] | |
lahf | |
jmp cycl | |
@ee: ; inc aaaa | |
getabs | |
sahf | |
inc byte ptr [bx] | |
lahf | |
Cycle | |
@fe: ; inc aaaa,x | |
getabsx | |
sahf | |
inc byte ptr [bx] | |
lahf | |
jmp cycl | |
@e8: ; inx | |
sahf | |
inc x | |
lahf | |
Cycle | |
@c8: ; iny | |
sahf | |
inc y | |
lahf | |
Cycle | |
@4c: ; jmp aaaa | |
mov si,[si] | |
Cycle bh0 | |
@6c: ; jmp (aaaa) | |
mov si,[si] | |
mov si,[si] | |
Cycle bh0 | |
@20: ; jsr aaaa | |
cmp bp,102h | |
jb jsr2 | |
inc si | |
mov word ptr ds:[bp-1],si | |
sub bp,2 | |
mov si,[si-1] | |
Cycle bh0 | |
jsr2: | |
mov di,ax | |
mov ax,si | |
inc ax | |
mov bx,bp | |
mov byte ptr [bx],ah | |
dec bl | |
mov byte ptr [bx],al | |
dec bl | |
mov bp,bx | |
mov si,[si] | |
mov ax,di | |
jmp cycl | |
@a9: ; lda #aa | |
lodsb | |
mov acc,al | |
sahf | |
inc al | |
dec al | |
lahf | |
Cycle | |
@a5: ; lda aa | |
getzp | |
movor acc | |
Cycle bh0 | |
@b5: ; lda aa,x | |
getzpx | |
movor acc | |
Cycle bh0 | |
@ad: ; lda aaaa | |
getabs | |
ifio <movor acc> | |
@bd: ; lda aaaa,x | |
getabsx | |
ifio <movor acc> | |
@b9: ; lda aaaa,y | |
getabsy | |
ifio <movor acc> | |
@a1: ; lda (aa,x) | |
getindx | |
ifio <movor acc> | |
@b1: ; lda (aa),y | |
getindy | |
ifio <movor acc> | |
@a2: ; ldx #aa | |
lodsb | |
mov x,al | |
sahf | |
inc x | |
dec x | |
lahf | |
Cycle | |
@a6: ; ldx aa | |
getzp | |
movor x | |
Cycle bh0 | |
@b6: ; ldx aa,y | |
getzpy | |
movor x | |
jmp cycl | |
@ae: ; ldx aaaa | |
getabs | |
ifio <movor x> | |
@be: ; ldx aaaa,y | |
getabsy | |
ifio <movor x> | |
@a0: ; ldy #aa | |
lodsb | |
mov y,al | |
sahf | |
inc y | |
dec y | |
lahf | |
Cycle | |
@a4: ; ldy aa | |
getzp | |
movor y | |
Cycle bh0 | |
@b4: ; ldy aa,x | |
getzpx | |
movor y | |
jmp cycl | |
@ac: ; ldy aaaa | |
getabs | |
ifio <movor y> | |
@bc: ; ldy aaaa,x | |
getabsx | |
ifio <movor y> | |
@4a: ; lsr A | |
sahf | |
shr acc,1 | |
lahf | |
Cycle bh0 | |
@46: ; lsr aa | |
getzp bh0 | |
sahf | |
shr byte ptr [bx],1 | |
lahf | |
Cycle bh0 | |
@56: ; lsr aa,x | |
getzpx bh0 | |
sahf | |
shr byte ptr [bx],1 | |
lahf | |
jmp cycl | |
@4e: ; lsr aaaa | |
getabs | |
sahf | |
shr byte ptr [bx],1 | |
lahf | |
Cycle | |
@5e: ; lsr aaaa,x | |
getabsx | |
sahf | |
shr byte ptr [bx],1 | |
lahf | |
jmp cycl | |
@ea equ cycl ;nop | |
@9: ; ora #aa | |
lodsb | |
scf or,al,cycl | |
@5: ; ora aa | |
getzp bh0 | |
scf or,[bx],cycl | |
@15: ; ora aa,x | |
getzpx bh0 | |
scf or,[bx],cycl | |
@d: ; ora aaaa | |
getabs | |
scf or,[bx],cycl | |
@1d: ; ora aaaa,x | |
getabsx | |
scf or,[bx],cycl | |
@19: ; ora aaaa,y | |
getabsy | |
scf or,[bx],cycl | |
@1: ; ora (aa,x) | |
getindx | |
scf or,[bx],cycl | |
@11: ; ora (aa),y | |
getindy | |
scf or,[bx],cycl | |
@48: ; pha | |
pushon acc | |
Cycle | |
@8: ; php | |
mov bl,ah | |
rol bl,1 | |
rol bl,1 | |
and bl,7 | |
mov al,phptbl[bx] | |
or al,flags | |
pushon al | |
Cycle | |
@68: ; pla | |
pulloff acc | |
sahf | |
inc acc | |
dec acc | |
lahf | |
Cycle | |
@28: ; plp | |
pulloff flags | |
mov bl,flags | |
and flags,allflags | |
or flags,orflags | |
rol bl,1 | |
and bx,7 | |
mov ah,plptbl[bx] | |
Cycle | |
rotate macro oper | |
mov al,[bx] | |
sahf | |
oper al,1 | |
inc al | |
dec al | |
lahf | |
mov [bx],al | |
endm | |
@2a: ; rol A | |
sahf | |
rcl acc,1 | |
inc acc | |
dec acc | |
lahf | |
Cycle bh0 | |
@26: ; rol aa | |
getzp bh0 | |
rotate rcl | |
Cycle bh0 | |
@36: ; rol aa,x | |
getzpx bh0 | |
rotate rcl | |
jmp cycl | |
@2e: ; rol aaaa | |
getabs | |
rotate rcl | |
Cycle | |
@3e: ; rol aaaa,x | |
getabsx | |
rotate rcl | |
jmp cycl | |
@6a: ; ror A | |
sahf | |
rcr acc,1 | |
inc acc | |
dec acc | |
lahf | |
Cycle bh0 | |
@66: ; ror aa | |
getzp bh0 | |
rotate rcr | |
Cycle bh0 | |
@76: ; ror aa,x | |
getzpx bh0 | |
rotate rcr | |
jmp cycl | |
@6e: ; ror aaaa | |
getabs | |
rotate rcr | |
Cycle | |
@7e: ; ror aaaa,x | |
getabsx | |
rotate rcr | |
jmp cycl | |
@40: ; rti | |
pulloff flags | |
pulloff al | |
pulloff ah | |
mov si,ax | |
mov bl,flags | |
and flags,allflags | |
rol bl,1 | |
and bx,7 | |
mov ah,plptbl[bx] | |
jmp cycl | |
@60: ; rts | |
cmp bp,1fdh | |
ja rts2 | |
mov si,word ptr ds:[bp+1] | |
add bp,2 | |
inc si | |
Cycle bh0 | |
rts2: | |
mov di,ax | |
mov bx,bp | |
inc bl | |
mov al,byte ptr [bx] | |
inc bl | |
mov ah,byte ptr [bx] | |
inc ax | |
mov si,ax | |
mov ax,di | |
jmp cycl | |
@e9: ; sbc #aa | |
lodsb | |
sahf | |
cmc | |
sbb acc,al | |
cmc | |
lahf | |
setovf | |
Cycle | |
@e5: ; sbc aa | |
getzp | |
sahf | |
cmc | |
sbb acc,[bx] | |
cmc | |
lahf | |
setovf | |
Cycle bh0 | |
@f5: ; sbc aa,x | |
getzpx | |
sahf | |
cmc | |
sbb acc,[bx] | |
cmc | |
lahf | |
setovf | |
jmp cycl | |
@ed: ; sbc aaaa | |
getabs | |
sahf | |
cmc | |
sbb acc,[bx] | |
cmc | |
lahf | |
setovf | |
Cycle | |
@fd: ; sbc aaaa,x | |
getabsx | |
sahf | |
cmc | |
sbb acc,[bx] | |
cmc | |
lahf | |
setovf | |
jmp cycl | |
@f9: ; sbc aaaa,y | |
getabsy | |
sahf | |
cmc | |
sbb acc,[bx] | |
cmc | |
lahf | |
setovf | |
jmp cycl | |
@e1: ; sbc (aa,x) | |
getindx | |
sahf | |
cmc | |
sbb acc,[bx] | |
cmc | |
lahf | |
setovf | |
jmp cycl | |
@f1: ; sbc (aa),y | |
getindy | |
sahf | |
cmc | |
sbb acc,[bx] | |
cmc | |
lahf | |
setovf | |
Cycle | |
@38: ; sec | |
or ah,1 | |
Cycle bh0 | |
@f8: ; sed | |
or flags,decmode | |
jmp cycl | |
@78: ; sei | |
or flags,irqdisable | |
jmp cycl | |
@85: ; sta aa | |
getzp | |
mov [bx],acc | |
Cycle bh0 | |
@95: ; sta aa,x | |
getzpx | |
mov [bx],acc | |
jmp cycl | |
@8d: ; sta aaaa | |
getabs <mov [bx],acc> | |
@9d: ; sta aaaa,x | |
getabsx <mov [bx],acc> | |
@99: ; sta aaaa,y | |
getabsy <mov [bx],acc> | |
@81: ; sta (aa,x) | |
getindx <mov [bx],acc> | |
@91: ; sta (aa),y | |
getindy <mov [bx],acc> | |
@86: ; stx aa | |
getzp | |
mov [bx],x | |
Cycle bh0 | |
@96: ; stx aa,y | |
getzpy | |
mov [bx],x | |
jmp cycl | |
@8e: ; stx aaaa | |
getabs <mov [bx],x> | |
@84: ; sty aa | |
getzp | |
mov [bx],y | |
Cycle bh0 | |
@94: ; sty aa,x | |
getzpx | |
mov [bx],y | |
jmp cycl | |
@8c: ; sty aaaa | |
getabs <mov [bx],y> | |
@aa: ; tax | |
mov x,acc | |
sahf | |
inc x | |
dec x | |
lahf | |
Cycle | |
@a8: ; tay | |
mov y,acc | |
sahf | |
inc y | |
dec y | |
lahf | |
Cycle | |
@ba: ; tsx | |
mov bx,bp | |
mov x,bl | |
sahf | |
inc x | |
dec x | |
lahf | |
Cycle | |
@8a: ; txa | |
mov acc,x | |
sahf | |
inc acc | |
dec acc | |
lahf | |
Cycle | |
@9a: ; txs | |
mov bl,x | |
mov bh,1 | |
mov bp,bx | |
Cycle | |
@98: ; tya | |
mov acc,y | |
sahf | |
inc acc | |
dec acc | |
lahf | |
Cycle | |
IOB0 db 1,60h,1,0,0,0,0,0,0,8,0,0,1,0,0,0,0,0 ;IOB table | |
sectran db 0,7,14,6,13,5,12,4,11,3,10,2,9,1,8,15 ;sector translation for boot | |
@37: ;special instruction | |
lodsb | |
cmp al,73h ;next byte has to be this | |
je doextrn | |
jmp cycl | |
doextrn: | |
push ax | |
lodsb | |
cmp al,4 | |
ja ext_cycl | |
mov bl,al | |
mov bh,0 | |
shl bx,1 | |
jmp word ptr cs:ext_codes[bx] | |
ext_cycl: | |
pop ax | |
jmp cycl | |
ext_kbd: | |
mov ah,0 | |
int 16h | |
or al,80h | |
mov acc,al | |
jmp ext_cycl | |
ext_disk: | |
push cx | |
push dx | |
push bp | |
push si | |
push es | |
push ds | |
push ds ;IOB segment | |
mov al,y | |
mov ah,acc | |
push ax ;IOB offset | |
mov cx,@data | |
mov ds,cx | |
call far ptr _RWTS | |
add sp,4 | |
rwtsexit: | |
pop ds | |
pop es | |
pop si | |
pop bp | |
pop dx | |
pop cx | |
mov bl,al | |
pop ax | |
and ah,254 ;clear carry | |
or bl,bl | |
jz norwtserr | |
or ah,1 ;set carry | |
norwtserr: | |
jmp cycl | |
ext_trak0: | |
push cx | |
push dx | |
push bp | |
push si | |
push es | |
push ds | |
mov IOB0[1],x ;slot | |
mov bl,byte ptr ds:[3dh] | |
mov bh,0 | |
mov al,sectran[bx] | |
mov IOB0[5],al ;sector | |
mov ax,word ptr ds:[26h] | |
mov word ptr IOB0[8],ax ;buffer | |
mov ax,offset IOB0 | |
push cs ;IOB seg | |
push ax ;IOB offset | |
mov cx,@data | |
mov ds,cx | |
call far ptr _RWTS | |
add sp,4 | |
jmp rwtsexit | |
ext_codes: | |
dw ext_cycl,ext_kbd,ext_cycl,ext_disk,ext_trak0 | |
; *** I/O HANDLERS | |
hiresofs: | |
dw 4 dup (0),4 dup (40),4 dup (80),4 dup (120) | |
dw 4 dup (160),4 dup (200),4 dup (240),4 dup (280) | |
dw 4 dup (0+2000h),4 dup (40+2000h),4 dup (80+2000h),4 dup (120+2000h) | |
dw 4 dup (160+2000h),4 dup (200+2000h),4 dup (240+2000h),4 dup (280+2000h) | |
textvid: | |
mov al,[bx] | |
push ax | |
and bh,3 | |
shl bx,1 | |
mov di,word ptr cs:textlkup[bx] | |
shl di,1 | |
js textskip | |
mov bl,al | |
mov bh,0 | |
shl bx,1 | |
mov ax,word ptr cs:textchar[bx] | |
stosw | |
textskip: | |
pop ax | |
ret | |
hiresmix: | |
cmp di,40*20*8 | |
jb hireskip | |
pop ax | |
call loresmix | |
ret | |
hiresvid: | |
mov al,[bx] | |
push ax | |
mov ah,bh | |
and bh,3 | |
shl bx,1 | |
mov di,word ptr cs:lorslkup[bx] | |
or di,di | |
js hireskip | |
mov bl,ah | |
cmp bl,0ch | |
jb hiresmix | |
sub bl,20h | |
mov bh,0 | |
; and bx,1fh | |
shl bl,1 | |
add di,word ptr cs:hiresofs[bx] | |
cmp di,40*20*8 | |
jb hires1 | |
test vidmix,2 ;in mix mode? | |
jz hireskip | |
hires1: | |
mov bl,al | |
mov bh,0 | |
mov al,byte ptr cs:graflkup[bx] | |
stosb | |
hireskip: | |
pop ax | |
ret | |
loresvid: | |
mov al,[bx] | |
and bh,3 | |
shl bx,1 | |
mov di,word ptr cs:lorslkup[bx] | |
or di,di | |
js loreskip | |
cmp di,40*20*8 | |
jb lores1 | |
test vidmix,2 | |
je loresmix | |
lores1: | |
REPT 4 | |
stosb | |
add di,39 | |
ENDM | |
REPT 4 | |
shr al,1 | |
ENDM | |
REPT 4 | |
stosb | |
add di,39 | |
ENDM | |
loreskip: | |
ret | |
loresmix: | |
mov bl,al | |
mov bh,0 | |
shl bx,1 | |
mov bl,byte ptr cs:textchar[bx] | |
and bx,7fh | |
shl bx,1 | |
shl bx,1 | |
shl bx,1 | |
add bx,0fa6eh ;character table in BIOS | |
push si | |
push ds | |
push dx | |
mov dx,03ceh | |
mov ax,5 | |
out dx,ax | |
mov si,bx | |
mov bx,0f000h | |
mov ds,bx | |
REPT 8 | |
movsb | |
add di,39 | |
ENDM | |
mov al,2 | |
out dx,al | |
pop dx | |
pop ds | |
pop si | |
ret | |
bitchng macro lab,state,bit | |
lab: test vidmix,bit | |
IF state | |
jnz bitret ;if bit = 1, exit | |
ELSE | |
jz bitret ;if bit = 0, exit | |
ENDIF | |
xor vidmix,bit | |
endm | |
bitchng grmode,1,1 | |
jmp draw_screen | |
bitchng txmode,0,1 | |
jmp draw_screen | |
bitchng nomix,1,2 | |
test vidmix,1 ;is graphics mode? | |
jz bitret | |
jmp draw_screen | |
bitchng mix,0,2 | |
test vidmix,1 ;is graphics mode? | |
jz bitret | |
push ax | |
push bx | |
push cx | |
push si | |
call @drawtextbot | |
pop si | |
pop cx | |
pop bx | |
pop ax | |
ret | |
bitret: ret | |
bitchng page0,0,4 | |
jmp flip_page | |
bitchng page1,1,4 | |
jmp flip_page | |
bitchng lores,0,8 | |
test vidmix,1 ;is graphics mode? | |
jz bitret | |
jmp draw_screen | |
bitchng hires,1,8 | |
test vidmix,1 ;is graphics mode? | |
jz bitret | |
jmp draw_screen | |
; OTHER I/O STROBES | |
clearstrobe: | |
push cx | |
mov di,0c000h | |
mov al,[di] | |
and al,7fh | |
mov cx,16 | |
clstblp: | |
mov [di],al | |
inc di | |
loop clstblp | |
pop cx | |
ret | |
spkrout: | |
in al,61h | |
xor al,2 | |
out 61h,al | |
ret | |
IRP N,<1,2,4,8> | |
LOCAL nogame | |
gc&N&: | |
push dx | |
mov dx,201h | |
in al,dx | |
and al,N | |
jz nogame | |
or al,80h | |
nogame: mov [bx],al | |
pop dx | |
ret | |
ENDM | |
gmstrobe: | |
push dx | |
mov dx,201h | |
out dx,al | |
pop dx | |
ret | |
IOret: ret | |
IOpage: | |
dw 16 dup (IOret) ;key input | |
dw 16 dup (clearstrobe) | |
dw 16 dup (IOret) ;cassette out | |
dw 16 dup (spkrout) | |
dw 16 dup (IOret) ;utility strobe | |
dw grmode,txmode | |
dw nomix,mix | |
dw page0,page1 | |
dw lores,hires | |
dw 8 dup (IOret) ;annunciators | |
REPT 2 | |
dw IOret ;cassette in | |
dw 3 dup (IOret) ;paddle buttons | |
dw gc1,gc2,gc4,gc8 ;game controllers | |
ENDM | |
dw 16 dup (gmstrobe) ;game strobes | |
dw 128 dup (IOret) ;I/O ports | |
doIO: | |
mov di,bx | |
and di,0ffh | |
shl di,1 | |
jmp word ptr cs:IOpage[di] | |
_storebyte PROC FAR | |
PUBLIC _storebyte | |
ARG adr,val:WORD | |
push bp | |
mov bp,sp | |
push di | |
push ds | |
push es | |
mov ds,dsseg | |
mov es,esseg | |
mov cx,val | |
mov bx,adr | |
mov al,bh | |
mov di,ax | |
and di,0ffh | |
test IOmap[di],255 | |
jnz @2fish | |
mov [bx],cl | |
stobend: | |
pop es | |
pop ds | |
pop di | |
pop bp | |
retf | |
@2fish: cmp bh,0c0h | |
je @2IO | |
ja stobend | |
mov [bx],cl | |
call vidout | |
jmp stobend | |
@2IO: call near ptr doIO | |
jmp stobend | |
_storebyte ENDP | |
textlkup: | |
INCLUDE textlkup.tbl | |
lorslkup: | |
INCLUDE lorslkup.tbl | |
graflkup: | |
INCLUDE graflkup.tbl | |
textchar: | |
dw 256 dup (?) | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment