Skip to content

Instantly share code, notes, and snippets.

@sehugg
Created January 7, 2017 14:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sehugg/6218e965ddfcf2445011c44b8643fe36 to your computer and use it in GitHub Desktop.
Save sehugg/6218e965ddfcf2445011c44b8643fe36 to your computer and use it in GitHub Desktop.
An Apple ][ emulator in 8086 assembler
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