Tem é de se ter alguns cuidados nomeados no primeiro artigo, especialmente manter o stack abaixo de $C000 / 49152, a própria rotina que trata da paginação, e a rotina de interrupt, fora da gama de endereços $C000-$FFFF.
$FFFF
-
$C000
|
Bank 0
|
Bank 1
|
Bank 2
|
Bank 3
|
Bank 4
|
Bank 5
(screen 0)
|
Bank 6
|
Bank 7
(screen 1)
|
$BFFF
-
$8000
|
Bank 2
| |||||||
$7FFF
-
$4000
|
Bank 5
(screen 0)
| |||||||
$3FFF
-
$0000
|
ROM 0
|
ROM 1
|
Também pela disposição dos bancos de RAM, o banco 5 e banco 2 não vale a pena usar, por estarem permanentemente mapeados em $4000 e $8000. Existe também a ressalva do IM 1 estar a usar variáveis no banco 7, portanto se se pretender usar o banco 7, tem de se usar IM 2. Logo, os restantes bancos (0-4 e 6, 7 com IM 2 (e sem voltar ao BASIC?)) podem ser usados para paginar código.
O código a ser paginado terá portanto de ser compilado nas múltiplas páginas em relação ao endereço $C000-$FFFF. Pode-se assim escrever uma rotina baixo de $C000, que invocamos quando quisermos saltar para rotinas na memória paginada. Uma possibilidade é definir o endereço C como pivot para escolher a página e função a ser chamada.
Por exemplo:
LD C,9 ; banco 0 - rotina de impressão
LD DE,MENSAGEM ; texto a imprimir
CALL PAGED_ROUTINES
---
;PAGED_ROUTINES
; C - 3 bits altos página ser paginada
; 4 bits baixos - rotina a invocar
PAGED_ROUTINES:
; select page
PUSH AF
PUSH BC
LD A,C
AND $E0 ; limpa tudo menos os 3 bits superiores (pagina/banco)
RLCA
RLCA
RLCA
LD C,A ; roda-os para os 3 bits inferiores, e deixa-os em C
LD A,($5B5C)
AND $F4
OR C ; selecciona banco C a paginar
LD BC,$7ffd
DI
LD ($5B5C),A ; deixa cópia
OUT (C),A ; e pagina página pretendida
EI
POP BC
; salta para rotina já na página nova
; limpa página de C, só para ficar com código de função a chamar nos 5 bits baixos
; 5 bits - 15 funções principais
LD A,C
AND $1F
LD C,A
POP AF
JP $C000
Nota: a rotina é ilustrativa, não foi testada.
Sem comentários:
Enviar um comentário