O documento descreve o desenvolvimento de um carregador rápido para os computadores TK-2000 e Apple II. O objetivo era criar um sistema operacional simples que carregasse arquivos e programas de forma eficiente, permitindo maior espaço livre na memória. O desenvolvedor analisou as arquiteturas dos computadores e planejou como programar em assembly de baixo nível para aproveitar os recursos de hardware.
1. Um Carregador Rápido para
TK-2000 e Apple II
que virou Sistema Operacional
http://tk2k.lisias.net/CB2k
2. Premissa
i.Restaurar um obscuro
computador doméstico de quase 30
anos de idade
ii.Escrever um sistema operacional
pro dito cujo
iii.?????
iv.PROFIT! :-)
5. As Vítimas
● Scene Retrô brasileira de Apple II e Compatíveis (ou quase)
– Intensa movimentação nos últimos 18 meses
● Inúmeras novidades
– engenharia reversa do Cartucho Controlador de Discos do TK-2000
– Tomato Board
5/89
6. O Motivo
● Acesso à Hardware equivalente, mais barato e
abundante, da linha Apple
● Mas os jogos (e parte significativa dos demais
softwares) ainda estavam em formato Cassete
● Soluções (software) prontas, importadas do Apple II,
eram
– Muito complexas para portar
● ProntoDOS, DiversiDOS, ProDOS
– todos ótimos, mas sistemas operacionais completos!
– Overkill
– Over memory :-)
6/89
7. Enquanto isto...
● “lá fora” (news:comp.sys.apple)
– CompatiBoot original (Raven/C700 Club)
● Rápida
● Prática
● Mas não adequada
– Capenga no TK-2000
– One shot only
– Altas gambiarras pra convencer a dita cuja a fazer o que
precisávamos
– Efeitos colaterais diversos e inesperados
7/89
8. Indo direto ao ponto
● Benchmark : TK-DOS 3.3
– Tempo entre ligar a máquina (com um disquete com boot no drive) e o Prompt do
Applesoft:
● 31 segs.
– Tempo para carregar uma tela gráfica HGR:
● 10 segs
– Espaço livre na RAM depois de carregado:
● ~ 24 Kbytes.
– Não, não é Mega. É Kilo mesmo! :-)
● Demais S.O.s
– Overkill
● Outras Soluções
– Não são práticos nem flexíveis
– São perdulários
– Não funcionam, ou o fazem porcamente, no TK-2000
8/89
9. O Crime
“Hummmm...”
Groo faz o que...
“Eu acho que faço melhor!”
9/89
10. Advertência
O uso indiscriminado e Podem causar danos
concomitante de irreversíveis à/ao
– Linguagem Assembler
– Sanidade mental
– Rotinas de Tempo Real
– Computadores Vintage
– Relacionamentos amorosos
– Conceitos (nem tão assim) – Vida social
avançados de Arquitetura de
Computadores e Sistemas
– Convivência familiar
Operacionais – Organização domiciliar
– Café, cerveja, pizzas, lanches e – Paz condominial
snacks
– EL&P, Rick Wakeman, Jean Michel
– Perímetro da sua cintura :-)
Jarre, Vangelis, Daft Punk e
Kraftwerk
Depois não digam que a culpa é minha!! :-)
10/89
11. Planejando a ação
● A CB2k deve:
– Carregar arquivos com a maior eficiência possível
– Permitir carregar programas que querem ocupar o
espaço onde normalmente ficaria o DOS
– Ser prática para criar/atualizar disquetes
– Oferecer uma API consistente para programação
– Fornecer exemplos de como desenvolver
aplicações
11/89
12. Planejando a ação
● A CB2k não pode deixar de:
– Ser extensível e portável
– Ficar pronta em umas 4 ou 5 semanas.
● Férias acabam!
– Ser útil e agregar valor
● Demais funcionalidades (rede, ambiente
gráfico, co-processamento, etc.)
– são totalmente fora de escopo
● Hoje! ;-)
12/89
13. It's coding time!
● BELEZA!!
Já sei o que quero fazer, agora é
só ligar a máquina e... Oh, wait...
– Como se programa nesta joça?
13/89
14. First Things First
code
“One does not simply walk into Mordor!”
Boromir, The Fellowship of the Ring
14/89
15. Programação de Baixo Nível
Não tem este nome à toa...
● O legendário 6502
● Arquitetura dos Computadores
– Apple II+
– MPF-II/TK-2000
– Semelhanças e diferenças entre as máquinas target
● Disquetes: um problema em tempo real
– A Shugart
– A Disk II do Woz
– Persistência de dados em mídias magnéticas
15/89
16. O 6502
● Registradores
● Instruções
● Clock Cycle Time
– Cycle para os íntimos
● T States
– A únidade básica de tempo do processador
– A únidade básica de ansiedade do programador
● Os diferentes Endereçamentos à memória
– O segredo do sucesso!
– A Salvação da Pátria!
● O primeiro RISC?
● Sucessores
– 65C02
– 65816
16/89
17. $0000 Zero Page
$0100 Stack
O 6502
A
7 6 5 4 3 2 1 0
X Y
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
S P
7 6 5 4 3 2 1 0 N V 1 B D I Z C
PC
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
● Load / Store ● Trasnfer ● ROR, ROL, SHL, SHR
– Pero no mucho! – AX, XA – A
Free Addresses – AY, YA #imm
● LD / ST ●
– XS, SX ● Abs
– [A,X,Y] #imm ● Branchs ● Abs,X
– A abs,X – EQ / NE (Zero Flag) ● Abs,Y
– A abs,Y MI / PO (Minus Flag)
– ● (Indi,X)
– A (indi,X) – CS, CR (Carry) ● (Ind),Y
– A (indi),Y – VS, VC (Overflow) ● ADC, SBC
● JMP ● P (Status) – A
– JMP abs – SEC, CLC ● #imm
– Etc Abs
– JMP (indi) ●
● INC / DEC ● Abs,X
● JSR / RTS
– A, X, Y ●
Abs,Y
● Stack – Abs ● (Indi,X)
– PHA / PLA – Abs,X (Ind),Y
$FF00 ●
ROM – PHP / PLP – Abs,Y Muito Mais! 17/89
$FFFF ●
18. O Apple II+
● Hardware
– Memory Mapped I/O
– Modos de vídeo
– Mapa da RAM
● ROM
– Principais entry-points
– Uso da Página Zero
● Console I/O
– Teclado
– Caracteres
18/89
19. $0000 Zero Page
O Apple II+
$0100 Stack
$0200 I/O Buffer
Free RAM
$0300 System Pointers
$0400
TEXT/GR Page 1 ● Buffer de I/O
$0800 – Usado pelo sistema (e pelo DOS) para
TEXT/GR Page 2 entrada e saída de dados
● Teclado
$1000
Free RAM
● Disco
$2000 ● Etc.
HGR 1 ● 2 Páginas de texto
$4000
– 1 delas pode ser usada para programação
HGR 2
● 2 Páginas de gráficos
– Ambas podem ser usadas para programação
$6000 ● A ROM pode ser “sombreada” por um
L.C. P0 mecanismo chamado “Language Card”
L.C. P1
Free RAM Saturn Bank 7
– A LC é dividida em 3 bancos
Main ● 1 Principal
● 2 Secundários, que dividem o mesmo
$C000 Mem Map I/O L.C. P0 L.C. P1 endereço
$C100 – A LC pode ser expandida através de bancos
Expansion Slot
ROM Saturn Bank 1 de memória
Main
$D000 ● Saturn 128Kb.
L.C. P0 L.C. P1
ROM Language Card
Main 19/89
$FFFF
20. O Apple II+
● Teclado “ASCII”
– Um uC faz o serviço sujo para você
– Curto e Grosso
● E simples de ler!
– Mas um saco para os jogos
● Control e Shift não são dectáveis sem mods
● Combinações de teclas (que não envolvem as
modificadoras acima) são impossíveis de
serem detectadas
– A segunda sobrescreve a primeira, e ponto final
● Caracteres
– ASCII
● Alfanuméricos
● Suporte à Minúsculas opcional (!!!)
– Inverso e Flash
20/89
21. O MicroProfessor II
e seu primo brasileiro
TK-2000
● Hardware
– Memory Mapped I/O
– Modos de vídeo
– Mapa da RAM
● ROM
– Principais entry-points
– Uso da Página Zero
● Console I/O
– Teclado
– Caracteres
21/89
22. $0000
$0100
Zero Page
Stack
O MicroProfessor II
e seu primo brasileiro
$0200 I/O Buffer
TK-2000
Free RAM
$0300 System Pointers
$0400 Free RAM
&
Some System Variables ● 2 páginas de gráficos
$0800
– Como não há modo texto, uma delas
Free RAM obrigatoriamente precisa estar em uso pelo
sistema
$2000 – O TK-DOS ocupa quase toda a página 2 :-(
HGR 1
● ROM pode ser programaticamente
$4000 HGR 1 substituída pelas Extra RAM
● Bloco I : 15.75 Kbytes
Free RAM ● Bloco II : 4 bancos de 16Kbytes
– 1 banco de 8 kbytes
$A000 – 2 sub-bancos de 4 kbytes
Bloco II/D P0 Bloco II/D P1
HGR 2 – Saturn 64Kb! :-)
Extra RAM ● O meu tem 128Kb! :-)
$C000 Mem Map I/O Bloco II/D
$C100
● Apenas um Bloco pode estar ativo num
momento
$D000 Bloco II/A P0 Bloco II/A P1
ROM
Extra RAM – Os bancos do Bloco II precisam escolher qual
Bloco I
Extra RAM página de 4 kbytes deve estar ativa
Bloco II/A
$FFFF 22/89
23. O MicroProfessor II
e seu primo brasileiro
TK-2000
● Teclado com a Matriz exposta
– Sem um MicroControlador pra fazer o serviço pesado
– Vantagens
● Acesso individual (e múltiplo!) ao estado de cada tecla
– permite algumas combinações interessantes para jogos
– Desvantagens
● Gasto de processamento para ler o teclado
● Principal e maior motivo da “má fama” do TK-2000
– A rotina do fabricante, oferecida no Manual Técnico
como alternativa à leitura do teclado do Apple II era
porca – simples assim
– Um dos principais artefatos secundários do projeto:
●
Uma rotina rápida de leitura de teclado! :-)
– Caracteres
● ASCII
– Alfanuméricos
– Sem suporte às minúsculas (!!!)
● Semigráficos Fonte: pág.21 TK2000/II Manual Técnico
Microdigital Eletrônica LTDA
23/89
24. $0000
$0100
Zero Page
Stack
O Apple //e & //c Zero Page
Stack
$0200
$0300
I/O Buffer
Free RAM
System Pointers
(porque todo castigo...) I/O Buffer
Free RAM
System Pointers
$0400 TEXT/GR 80TEXT/DGR
Page 1 Page 1
$0800
● Revisões
TEXT/GR 80TEXT/ DGR
Page 2 – Apple // Extended Page 2
$1000
Free RAM ● 6502 Free RAM
$2000 – Apple //c, //e Enhanced e Platinum
HGR 1 DHGR 1
●
65C02
$4000 ● “Mouse Chars”
HGR 2 ● DTEXT (80 COLs), DGR & DHGR DHGR 2
$6000
● 128Kb
– Mas num esquema totalmente diferente
Free RAM Free RAM
– Descreve isto, Lisias!
● Nah... Deixa quieto! =D
$C000 Mem Map I/O
$C100 Expansion Slot Extension
ROM ROM
$D000 L.C. P0 L.C. P1 L.C. P1 L.C. P0
Language Card ROM Language Card
Main Main
$FFFF 24/89
Main AUX
25. Resumo da Ópera
● As diferenças da ROM enchem o saco
– Oferecer uma camada de “abstração” da ROM seria bacana, mas
exigiria mais memória
● Mas não sai de graça
● As diferenças na memória principal são facilmente gerenciáveis
– Mas o mesmo não acontece com os bancos de memória estendida
● E lá se vão funcionalidades pela janela
● O 65C02 têm instruções extras que seriam (muito) úteis
– Maior densidade de código e mais “semântica” por ciclo de clock
● TXY (1 byte, 2 Ciclos)
– PHA ; TXA ; TAY ; PLA (4 bytes, 10 ciclos!)
– STX <ZP_ADDR>; LDY¨<ZP_ADDR> (4 bytes, 6 ciclos – mas gasta uma posição da ZP)
– STX <ABS_ADDR>; LDY <ABS_ADDR> (6 bytes, 8 ciclos)
– Mas alienaria o TK-2000 e o Apple II+
25/89
27. Mídias Magnéticas
● Revoluções Por Minuto
Mas sem as louras geladas... =/
– Densidade Magnética
● Coerção
● Histeresys
– Velocidade Angular “constante” versus
Velocidade Linear “constante”
● (Constante, o escambau! O motor não é estável...)
– Largura de Banda
– Desgaste físico!
27/89
28. Discos Magnéticos
● As trilhas não têm todas o mesmo tamanho físico.
– Perímetro é função do raio!
● Mas tem o mesmo tamanho lógico...
– Velocidade angular constante
● Densidade dos dados varia em função da trilha
● Pragmatismo
– A Shugart ajustou o mecanismo para ser confiável na trilha
mais interna, e desperdiçou densidade nas mais externas
– Drives mais sofisticados (e caros) variam a velocidade do
motor em função da trilha
● aproveitar melhor a densidade da mídia
28/89
29. Discos Magnéticos
● Os dados são gravados (re)alinhando polaridade na
superfície da camada de óxido de ferro
– Descobriu-se não ser eficiente usar uma polaridade para o bit 1,
e outra para o bit 0
● Mudança de polaridade na linha do tempo indica bit 1
● Não mudança de polaridade na linha do tempo indica bit 0
● Mas o motor não consegue fornecer uma velocidade
constante ao nível do microsegundo
– Pequenas variações no motor “distorcem” o comprimento de um
bit
– Dada uma distância longa o suficiente sem inversão de
polaridade, o hardware não sabe mais quantos bits '0' foram
lidos... 1 1 1 1 1 1 1 1 1 0 0 1 0 0 ? ?
● As inversões de fase, então, são usadas como “clock” para a leitura dos
dados
29/89
30. Discos Magnéticos
● Mas isto tudo foi problema da Shugart!
– E do Woz...
● E do Langhton!
– Quem? :-)
● Qual foi o meu problema?
– 32 * 1 / 1.023 MHz
● 0,0000031280547409579667644183773216031 Segundos
● É o tempo que se tem para ler um raw byte do disquete, salvar
na memória e estar pronto para ler o próximo!
● 3196 a 12787 bytes lidos a cada piscar de olhos
– E eu só preciso perder UM para causar o infame I/O Error!
30/89
32. Algoritmos de Tempo Real
● Quediaboéisso?
– São algoritmos em que o tempo de resposta faz parte do
resultado do processamento
●
Não é o mesmo que “fazer rapidinho”
– “Entregar” depois do prazo é o mesmo que não entregar. Ou entregar lixo.
– “Entregar” antes do prazo é desperdício de processamento
● E o Kiko? Kiko'eu tenho a ver com isto?
– Acessar disco é uma tarefa de tempo real
●
Missão Crítica!
– Computadores modernos possui um micro controlador
especializado para lidar com disco
● O Apple II não.
– Welcome to hell...
32/89
34. Reavaliação
● Riscos
– Gravar setores dá mais trabalho que ler
● E eu nem tinha certeza de que iria conseguir ler...
– Não vou conseguir fazer tudo!
● Muitas diferenças entre cada target, praticamente um
software diferente pra cada um
● Prioridades
– BOOT eficiente
– Carga rápida de Binários
– Serviços (mínimos) de diretório
– (nice) API
● Sólida
– Abrir mão da memória extra, e focar na principal
● E economizar onde der
34/89
35. Reação
● Começar prototipando as rotinas básicas de disco
– Se eu não estabilizar a rotina de leitura de setores, o resto
não serve de nada
– Um terço do esforço total do projeto foi gasto só nelas
● Redução de escopo
– Serviços de “Console I/O” pelo Kernel :-|
– Cache de disco (em especial, do CATALOG) :-|
– Gravação de Dados ¬¬
– Gerenciamento da memória ¬¬
– Relocação em memória X-(
– Suporte à programas BASIC X-(
35/89
36. Resolução
● “Internalizar” algumas funções da ROM para o S.O.
– Não sem conseqüências... ¬¬
● Delegar à aplicação gerenciar o resto do hardware
– O S.O. identifica para você a máquina em que está rodando
– “Bibliotecas” padrão no “User Space”
– E cada um que se vire!
● BASIC.SYSTEM
– Todo o suporte ao BASIC ficará ao cargo de uma (futura) “Aplicação” no
User Space.
● “Forkar” o Kernel para casos especiais
– Versões especializadas para cada arquitetura e/ou funcionalidade
específica
– Gerência de Configuração to the rescue! :-)
36/89
37. E o inesperado
(porque todo castigo...)
● O uso da Página Zero me mordeu o traseiro.
– Feio. :-(
– Quase assassinou o projeto no berço
● Quando a R*TS não matava o resto da máquina, o resto da máquina
matava a R*TS
● Cerca de 20% do esforço de desenvolvimento foi gasto mapeando e
documentando, corretamente, o uso da Z.P.
– No TK-2000 e no Apple II
– Um esforço com o qual eu não contava
– Não havia mais o que fazer exceto desistir ou pagar o pato e
seguir adiante
● 5 dias de trabalho indo pelo ralo.
– E as férias, digo, o prazo acabando! =]
● A única documentação formal do projeto.
37/89
38. ; Depends on rwts.def.
; Updates zp_profile.s
; Apple II Zero Page Usage
;
; Lo Nibble of Address
; Hi
; Nib 0 1 2 3 4 5 6 7 8 9 A B C D E F
; ----- ----- ------ ------ ----- ------ ----- ---- ---- ---- ---- ---- ----- ----- ----- -----
; 0 | A~ A~ A A A A - - - - A A A AI A A
; 1 | A A A A A A A A A A A A A A - M*
; 2 | M M M M M3 M MA3 MA3 M3 M3 M3 M3 MA3 MA3 M3 MA3
; 3 | MA M MA MA3 M M3 M3B M3B M3B M3B M~ M~ MA3~^ MA3~^ MA3~^ MA3~^
; 4 | M3~+^ M3~+^ M3~@^ M3~@^ M3~@^ M3~@ M3~ M3~ M3~ M3~ I3~ I3~ I3~ I3~ M~@# M@#
; 5 | MA MA MA MA MA* MAI* AI AI AI AI AI AI AI AI AI AI
; 6 | AI+ AI+ AI@ AI@ AI@ AI@ AI@# AI3 AI3 AI3 AI3 AI AI AI AI AI3
; 7 | AI3 AI AI AI3 AI3 AI AI3 AI AI AI AI AI AI AI AI AI
; 8 | AI AI AI AI AI AI AI AI@ AI@ AI AI AI AI AI AI AI
; 9 | AI AI AI AI AI AI AI AI AI AI AI AI AI AI AI AI
; A | AI AI AI AI AI AI AI AI AI AI AI AI AI AI AI AI3
; B | AI3 AI AI AI AI AI AI AI AI AI AI AI AI AI AI AI
; C | AI AI AI AI AI AI AI AI AI AI AI3 AI3 AI3 AI3 I# I#
; D | AI AI AI AI AI AI AI3 I! AI3 AI3 AI AI AI AI AI3 AI
; E | A A A A A A A A A A A ? - - - -
; F | A A A A A A A A A A - - - - Ik AI
;
;
; M = Used by Monitor; * used in early Apple IIe ROMs-- now free
; A = Used by Applesoft BASIC
; I = Used by Integer BASIC
; 3 = Used by DOS 3.3
; ~ = Used by ProDOS ($40-$4E is saved before and restored after use)
; B = Used by ProDOS BASIC.SYSTEM (also uses all Applesoft locations)
; - = Free; not used
;
; k = Used by TK-2000 / MPF-II
;
; + = RWTS, Comunicação com "Cliente"
; @ = RWTS, Conteúdo descartável.
; ! = RWTS, Posição Chave: não pode ser mudada nem destruída!
;
; ^ = CompatiBoot 2k, Comunicação com "Cliente"
; # = CompatiBoot 2K, Conteúdo descartável.
; ? = CompatiBoot 2K, Posição Chave: não pode ser mudada nem destruída!
;
; --Bryan Dunphy, Michael J. Mahon, Rubywand, CompatiBoot 2k
38/89
39. E quando tudo o mais falhar...
“How many times do I have to tell you,
the right tool for the right job!”
Montgomery Scott (Scotty)
Chief Engineer, NCC-1701-A USS Enterprise
39/89
41. Anatomia de um
Disquete
35 Trilhas
0 1 2 … 35
Address Field
gapzão gapzão gapzão gapzão
14
Addr_0 Addr_0 Addr_0 3 2 Addr_0
2 2 2 3
gap gap gap Prologo Volume gap
Track Sector ChkSum Epilogo
Data Data Data 'D5 AA 96 '4 & 4 encoding '4 &Data
4 encoding '4 & 4 encoding '4 & 4 encoding 'DE AA EB
=4096 bytes (lógicos)
gap gap gap gap
Addr_1 Addr_1 Addr_1 Addr_1
~48000 bits (raw)
gap gap gap gap Data Field
Data Data Data Data 349
gap gap gap 3 gap
342 1 3
Addr_2 Addr_2 Addr_2 Prologo Addr_2
Data ChkSum Epilogo
gap gap gap 'D5 AA AD gap
6 & 2 encoding 'XX 'DE AA EB
Data Data Data Data
gap gap gap gap
Addr_3 Addr_3 Addr_3 … “gapzãp” Addr_3“Self Sync bytes” gap
gap gap gap 48 a 100 gap 5 a 60
Data Data Data 'FF FF FF … Data 1 1 1 1 1 1 1 0 0
'1 'FF FF FF
gap gap gap gap
Addr_4 Addr_4 Addr_4 Addr_4
gap gap gap gap
Data Data Data Data
gap gap gap gap
… … … …
Addr_15 Addr_15 Addr_15 Addr_15
gap gap gap gap
Data Data Data Data
41/89
43. Boot
● Power On RESET
– RESET Vector
● Autostart ROM (BOOT 0)
– Busca por uma placa DISK II na ROM de expansão
● BOOT 1 (second stage)
– Trilha 0, Setor 0
– L-Boot1
● BOOT 2 (third stage)
– Sistema Operacional
Ou outro payload qualquer...
43/89
44. A L-Boot1
● Fornece a melhor performance possível para carga
sequêncial
– Multi trilha
● Serviços independentes de “plataforma”
– Impressão em tela
– Carga de setores
– Descompressão de dados
● Também foi usada com sucesso:
– Boot do TK-DOS 3.3
– Boot do Apple DOS 3.3
– Jogos stand-alone
44/89
45. Finalmente: CB2k
● R*TS
● Kernel
– Serviços de Diretório
– Serviços “Raw Files”
– Serviços Binary Files
– Serviços de House Keeping
45/89
47. O Supervisor
● A instrução mágica
– BRK
KERNEL_SUPERVISOR:
cli ; Desativamos interrupções.
; O Kernel não sabe ser interrompido, e a R*TS *NÃO PODE* ser interrompida!
; A RTI abaixo restaurará o Status, e se a IRQ estava ativada, ela voltará a
estar.
.ifndef LANGUAGE_CARD
jsr MON_RESTORE ; Pois é... A ROM do Apple IIe faz o favor de,
; trabalho fodástico de resetar o estado da
; anterior para permitir restauro!), tirar da
; (o que eu não queria), e *não manter* o
; virtualmente fodendo com o conceito de
;
; TODO: Mover a CB2K para Language Card, escrever
.endif
jsr __SAVE_THE_WORLD
ldx KERNEL_SUPERVISOR__STACKPOINT ; O Supervisor *NÃO É* reentrante.
bne @PANIC
lda __REG_P
and #%00010000 ; Checa se o BRK STATUS está ativo
beq @PANIC ; Se não está, a máquina tá despirocada e o PC caiu
; aqui por acidente!
47/89
48. A (nice) API
.define VERSION_MAJOR 1
.define VERSION_MINOR 1
.define VERSION_RELEASE "2012.0901"
.macro SYS syscall
BRK
.byte syscall
.endmacro
; This two entries are garanteed to never change or be renamed!
CB2K_SYSTEM_PANIC := 0
CB2K_SYSTEM_IDENTIFICATION := 2 + CB2K_SYSTEM_PANIC
; The following entries can, but is unlikely to, change on MAJOR versions.
CB2K_FILE_LOAD := 2 + CB2K_SYSTEM_IDENTIFICATION
CB2K_FILE_RUN := 2 + CB2K_FILE_LOAD
CB2K_FINISH := 2 + CB2K_FILE_RUN
CB2K_FILE_SET := 2 + CB2K_FINISH
CB2K_FILE_QUERY := 2 + CB2K_FILE_SET
CB2K_FILE_GET := 2 + CB2K_FILE_QUERY
CB2K_RAWFILE_SEEK := 2 + CB2K_FILE_GET
CB2K_RAWFILE_READ := 2 + CB2K_RAWFILE_SEEK
CB2K_HANDLER_SET := 2 + CB2K_RAWFILE_READ
CB2K_CONFIGURATION_SET := 2 + CB2K_HANDLER_SET
CB2K_CONFIGURATION_GET := 2 + CB2K_CONFIGURATION_SET
CB2K_SECTOR_READ := 2 + CB2K_CONFIGURATION_GET
; The following entries (if any) can be added on MINOR versions
; CB2K_FUTURE_EXPANSION := 2 + CB2K_SECTOR_READ
48/89
49. Resultados
● Footprint 3.75Kbytes
– Kernel, R*TS, Supervisor, buffers, tudo!
– E os buffers ainda são configuráveis (on the fly)
● Melhor performance
– 6 a 7 Kbytes/s – próximo do limite operacional do dispositivo
● Usa discos formatados pelo Apple DOS 3.3
– Até o FID pode ser usado para povoar seus discos
● Mas eu recomendo o CiderPress. :-)
● Aplicações
– Game Loaders
– Demos
– Outros
49/89
50. Resultados
● Benchmark TK-2000
– Tempo entre ligar a máquina (com o disquete já no drive) e o Prompt
do Applesoft :
● DOS: ~31 Segundos (!!!!)
● CB2k: 6 segundos
● DOS + LBoot1: 7 segundos (!!!!)
– Tempo para carregar uma tela HGR:
● DOS: 10 segundos
●
CB2k: 4 segundos
– Espaço livre na RAM (MEMTOP - $800):
● DOS: $9600 - $800 = $8E00 = 35.5Kb
●
CB2k: $B000 - $800 = $A800 = 42Kb
● Mas convêm lembrar:
– A CB2k faz pouca coisa mais que carregar binários
50/89
51. Por que o DOS é tão lento?
● Os “raw sectors” (342 bytes físicos) são lidos
para um buffer intermediário
● Este buffer é então decodificado para os 256
bytes de dados, em um buffer auxiliar
● Estes dados são, finalmente, copiados para o
buffer de I/O para leitura pelo programa
BASIC ou para a memória destino, se binário
● E o disco continua virando
51/89
53. E por que a R*TS ficou tão
“rápida”?
● Os raw sectors são decodificados on the fly, indo diretamente para a
memória a que se destinam
– Sem buffers intermediários, sem memory moves
– Exceto o primeiro e o último setor de arquivos binários, que são carregados
num buffer de I/O e então copiados para o target para não sobrescrever
memória limítrofe
● Era o mais perverso efeito colateral da CompatiBoot original, diga-se de passagem
● Ela não espera pelo próximo setor, mas monta uma lista dos setores
desejados e vai carregando na medida em que eles passam debaixo
do cabeçote
– Não há espera pelo “próximo setor”
– Os gap bytes me dão tempo suficiente para recomeçar a leitura entre o fim de
um setor e o começo do outro
– Mesmo o pior caso leva apenas uma revolução do disquete para ser lido.
53/89
55. Mas então...
● Por que não consertaram antes?
– Consertaram!
● Apple
– ProDOS
● Terceiros
– ProntoDOS
– DiversiDOS
– CP/M
– Mas nenhum deles foi portado para o TK-2000!
● CB2k! :-)
– Nem implementaram leitura múltipla!
● CB2k! ;-)
55/89
57. Check List
● Café ● Instruções de onde baixar e
como instalar:
● Salgadinhos – MINGW
– CC65
● Daft Punk na – CiderPress
vitrolinha :-) – AppleWin
● Estes Slides – Emulador TK2000
● Os fontes do Hello Word
● Imagem de disco – Leia o READ.ME ! ;-)
da CB2k (1.1r4a:Set/2012) ● Instruções:
– Para montagem do programa,
– Importação do binário para uma
imagem de disquete
– e execução em emulador.
57/89
64. Hello World
● LOOP (até "6502" a linha da primeira zString seja menor que 0)
.setcpu que : lda (PRINT_DATA),y
.localchar '@' beq :+
jsr PRINT_ASCII
– PRINT (macro em SYSTEM.DEF)
.include "../hw.def" iny
.include "../sys.def" bne :-
Imprime <n> zStrings
.include
● "../bios.def" (terminada em 0, C-style) em
inc posições específicas da tela
PRINT_DATA+1
bne :-
● (Rotina de SYSTEM.INC)
.include "../CB2k.def" :
jsr ANYKEY
– Pausa de ~25 mSecs
.include "system.def" jsr
SYS
SYSTEM_HGR
CB2K_FILE_LOAD
.org $800 jsr ANYKEY
● (Rotina na ROM)
NO_FUN:
–
jsr NotarSYSTEM_INIT
que MON_WAIT sempre volta com ZeroFlag em 0.
jmp SYSTEM_APPLESOFT_START_COLD
ldy #CB2K_HANDLER_ERROR ANYKEY:
● ldaNotar os branchs relativos anônimos!
ldx
#<NO_FUN
#>NO_FUN
PRINT
jmp
ANYKEY_TEXT
MON_RDKEY
SYS CB2K_HANDLER_SET
HEADER:
: HEADER_line_0:
PRINT HEADER .byte 22,0
dec HEADER_line_1 textz "============ Hello World !! ============"
dec HEADER_line_0 HEADER_line_1:
bmi :+ .byte 23,0
lda #90 textz " "
jsr MON_WAIT .byte 1,0,0
beq :- ; Branch always! .byte -1
:
ANYKEY_TEXT:
lda #<MENSAGEM_TEXT .byte 23,0
ldx #>MENSAGEM_TEXT textz ":"
sta PRINT_DATA .byte -1
stx PRINT_DATA+1
.include "system.inc"
ldy #0
MENSAGEM_TEXT:
.include "mensagem.txt"
64/89
65. Hello World
● Dois loops:
.setcpu "6502" : lda
beq
(PRINT_DATA),y
:+
.localchar '@'
– O interno, “driven” pelo Y jsr PRINT_ASCII
.include "../hw.def" iny
● O INY “overflows” para 0 depois do 255.
.include "../sys.def" bne :-
● BNE :.include último resultado da ULA não deu em zero
pula se o "../bios.def" inc PRINT_DATA+1
bne :-
– O externo, “driven” pelo último valor lido em Acc
.include "../CB2k.def" :
jsr ANYKEY
BEQ: .include "system.def" em Acc for zero, sai do
● Se o último byte carregado jsr SYSTEM_HGR
loop. SYS CB2K_FILE_LOAD
.org $800
– BEQ/BNE e outros atuam em cima do Registrador jsr ANYKEY
de Status (P) NO_FUN:
jsr reflete o SYSTEM_INIT operação da ULA, ou da
●Que status da última jmp SYSTEM_APPLESOFT_START_COLD
última carga em registrador
ldy #CB2K_HANDLER_ERROR ANYKEY:
– PRINT_ASCII#<NO_FUN
lda PRINT ANYKEY_TEXT
ldx #>NO_FUN jmp MON_RDKEY
● Imprime o caractere ASCII no Acc
SYS CB2K_HANDLER_SET ● PRINT_DATA
HEADER:
●
:
Dirty and Tricky! HEADER_line_0:
– Duas posições na página zero (escolhidas à
PRINT HEADER .byte 22,0
– Eu sei que a única forma do INC dar em zero é
dec HEADER_line_1
PRINT_DATA HEADER_line_0
acabar apontando para a página zero
dedo!) para servir deHello World !! ============"
textz "============ ponteiro para o buffer do
dec HEADER_line_1:
–bmi nunca :+ armazena strings! ;-)
onde se texto a 23,0 impresso
.byte ser
lda #90 textz " "
– Na prática, pula sempre! – Estas instruções ocupam 2 bytes, e não 3!
.byte 1,0,0
jsr MON_WAIT
beq :- ; Branch always! .byte -1
:
● Usaremos o Y como indexador no loop que
lda #<MENSAGEM_TEXT
vem a seguir
ANYKEY_TEXT:
.byte 23,0
ldx #>MENSAGEM_TEXT textz ":"
sta PRINT_DATA – Inicializa em
.byte -1 0!
stx PRINT_DATA+1
.include "system.inc"
ldy #0
MENSAGEM_TEXT:
.include "mensagem.txt"
65/89
66. Hello World
.setcpu "6502" : lda (PRINT_DATA),y
.localchar '@' beq :+
jsr PRINT_ASCII
.include "../hw.def" iny
● Aguarda por"../sys.def"
.include
uma tecla (não
.include "../bios.def"
bne
inc
:-
PRINT_DATA+1
importa qual"../CB2k.def"
.include :
bne
jsr
:-
ANYKEY
.include "system.def" jsr SYSTEM_HGR
● Entra em modo gráfico
.org $800
SYS
jsr
CB2K_FILE_LOAD
ANYKEY
● Carrega o SYSTEM_INIT arquivo
jsr próximo NO_FUN:
jmp SYSTEM_APPLESOFT_START_COLD
binário do #CB2K_HANDLER_ERROR
ldy
lda
catálogo
#<NO_FUN
ANYKEY:
PRINT ANYKEY_TEXT
ldx #>NO_FUN jmp MON_RDKEY
– É uma tela HGR
SYS CB2K_HANDLER_SET
HEADER:
: HEADER_line_0:
EuHEADERHEADER_line_1 coloquei lá!
PRINT
●
dec
sei, fui eu que .byte 22,0
textz "============ Hello World !! ============"
– A CB2k já o deixou 'na agulha'
dec
bmi
HEADER_line_0
:+
HEADER_line_1:
.byte 23,0
lda #90 textz " "
quando carregou o programa
jsr MON_WAIT .byte 1,0,0
.byte -1
beq :- ; Branch always!
: corrente, basta a chamada para ANYKEY_TEXT:
carregá-lo
lda
ldx
#<MENSAGEM_TEXT
#>MENSAGEM_TEXT
.byte 23,0
textz ":"
sta PRINT_DATA .byte -1
● Ver CB2K_FILE_SET se não é o que
stx PRINT_DATA+1
.include "system.inc"
você quer
ldy #0
MENSAGEM_TEXT:
.include "mensagem.txt"
66/89
67. Hello World
.setcpu "6502" : lda (PRINT_DATA),y
.localchar '@' beq :+
jsr PRINT_ASCII
.include "../hw.def" iny
.include "../sys.def" bne :-
.include "../bios.def" inc PRINT_DATA+1
bne :-
.include "../CB2k.def" :
● Aguarda.include "system.def"
por outra tecla jsr
jsr
ANYKEY
SYSTEM_HGR
SYS CB2K_FILE_LOAD
● Encerra,.org $800
inicializando o Applesoft. jsr ANYKEY
NO_FUN:
– A CB2k ainda tá na memória, mas não dá
jsr SYSTEM_INIT jmp SYSTEM_APPLESOFT_START_COLD
suporte ao BASIC
ldy #CB2K_HANDLER_ERROR ANYKEY:
lda #<NO_FUN PRINT ANYKEY_TEXT
– Mas você pode brincar no MiniAssembler!
ldx
SYS
#>NO_FUN
CB2K_HANDLER_SET
jmp MON_RDKEY
HEADER:
:
● Se você estiver num Apple //e ou num TK- HEADER_line_0:
PRINT HEADERa Tomato Board revisada
2000 com HEADER_line_1 .byte 22,0
dec textz "============ Hello World !! ============"
dec HEADER_line_0 HEADER_line_1:
bmi :+ .byte 23,0
lda #90 textz " "
jsr MON_WAIT .byte 1,0,0
beq :- ; Branch always! .byte -1
:
ANYKEY_TEXT:
lda #<MENSAGEM_TEXT .byte 23,0
ldx #>MENSAGEM_TEXT textz ":"
sta PRINT_DATA .byte -1
stx PRINT_DATA+1
.include "system.inc"
ldy #0
MENSAGEM_TEXT:
.include "mensagem.txt"
67/89
Notas del editor
As Interfaces de Disco e Drives de Apple II são relativamente baratos E, de um mês para outro, diversos TK-2000 ganharam acesso à disquetes! Mas os jogos (e parte significativa dos demais softwares) ainda estavam em formato Cassete (ou equivalentes modernos como MP3 e CT2) sendo carregados pela porta de Audio! Convertê-los para formato de arquivo é relativamente fácil ainda em andamento, na medida em que os títulos são resgatados Fazê-los funcionar debaixo do TK-DOS nem tanto E não enlouquecer esperando o boot acontecer ainda menos. Soluções importadas do Apple II não atendiam As diferenças estruturais entre as máquinas não permitem um reuso direto As soluções simples invariavelmente eram limitadas ou incômodas Não extensíveis, não adaptáveis Hacks interessantes e úteis, mas feitos por hackers para hackers e resolvem um problema específico com o menor custo As soluções completas eram muito complexas para portar ProntoDOS, DiversiDOS, ProDOS todos ótimos, mas sistemas operacionais completos! Overkill Over memory :-)
Enquanto isto, “lá fora” (news: comp.sys.apple ) Com problemas parecidos, soluções “ quick & dirty ” foram desenvolvidas e publicadas, dentre elas a CompatiBoot original (Raven/C700 Club) teve boa recepção na lista appleII_br Hiper rápida “ Herdeira” das rotinas de disco usadas na eZine francesa Dox-a-gaz (circa 1988), de autoria de Max-a-gaz. “ Herdeira” do utilitário de cópias “Locksmith”, da Omega Microware (circa 1985) Super prática Basta copiar o binário para a primeira entrada do catálogo e dar boot. Mas capenga no TK-2000 One shot only Altas gambiarras pra convencer a dita cuja a fazer o que queríamos Efeitos colaterais diversos e inesperados
O Apple/TK DOS 3.3 É muito “grande” É muito lerdo Demais S.O.s Overkill Fast Loaders legados Não são práticos nem flexíveis um saco criar o disco de boot! Armazenam dados controlando diretamente os setores do disco Sem diretórios Atualização/manutenção impraticável São perdulários Um disco por jogo, mesmo que 10 deles caibam no disquete Não funcionam, ou o fazem porcamente, no TK-2000
A CB2k deve: Carregar arquivos com a maior eficiência possível Ninguém quer esperar pra brincar! Permitir carregar programas que querem ocupar o espaço onde normalmente ficaria o DOS menor footprint possível na memória principal (a mais concorrida) deve permitir ser movida para diferentes posições de memória Para se acomodar mesmo com aqueles jogos “mais chatos” Ser prática para criar/atualizar disquetes Usar o formato do Apple DOS 3.3 Todo mundo conhece Ferramentas conhecidas para suporte A CB2k também deve: Oferecer uma API consistente para programação API deve proteger as aplicações de: Mudanças nos endereços das rotinas do kernel (assim eu posso movê-lo pra cima e pra baixo, de acordo com a conveniência) Mudanças de formato de mídia (e até mesmo de mídia!) Disquetes estão ficando raros Facilitar Novas Aplicações! Jogos multi-partes (Karateka) Jogos BASIC com mais memória disponível Algo importante principalmente para o TK-2000 Menus para os jogos Demos Fornecer exemplos de como desenvolver aplicações Sistemas Operacionais não são nada sem aplicações!
A CB2k não pode deixar de: Ser extensível e portável Outras arquiteturas baseadas em 6502 (porque não?) Outras mídias (porque não?) Ficar pronta em umas 4 ou 5 semanas. Férias acabam! Ser útil e agregar valor Na boa: ninguém precisa de ainda outra solução meia-boca pra ficar quebrando galho... Demais funcionalidades (rede, ambiente gráfico, co-processamento, etc.) são totalmente fora de escopo. Linus é um cara legal, não quero concorrer com ele! ;-) Ele ganha...
Logo, não posso gravar qualquer byte no disco, pois algumas combinações de bits não são legíveis Boa parte dos bits são “desperdiçados”, pois têm que ficar obrigatoriamente em '1' Para gerar a inversão de fase, que serve de clock para a identificação dos bits... Codificações usadas pela indústria: GCR – Group Code Recording Adotada pelo Apple Originalmente, a interface Disk II não conseguia ler dois bits '0' seguidos Codificação 5x3 – 5 bits de dados intercalados com 3 bits '1' de clock Numa revisão posterior do hardware, o hardware passou a ser capaz de detectar 2 bits 0 seguidos (mas apenas uma vez por byte) Codificação 6x2 – 6 bits de dados intercalados com 2 bits '1' de clock, MFM – Modified Frequency Modulation RLL - Run Lenght Limited EFM – Eight to Fourteen Modulation Outras
Quediaboéisso? São algoritmos em que o tempo de resposta faz parte do resultado do processamento Não é o mesmo que “fazer rapidinho” Um determiado processamento pode precisar ficar pronto só em 24 horas Ou 24 milisegundos... “ Entregar” depois do prazo é o mesmo que não entregar. Ou entregar lixo. “ Entregar” antes do prazo é desperdício de processamento Que pode ser necessário para entregar outra tarefa que está vencendo antes E o Kiko? Kiko'eu tenho a ver com isto? Acessar disco é uma tarefa de tempo real Missão Crítica! Se você não ler a porta de I/O no milisegundo correto, você não leu nada. Se você não gravar na porta de I/O no millisegundo adequado, você destruiu os dados que estavam no disquete! Computadores modernos possui um micro controlador especializado para lidar com disco O Apple II não. Welcome to hell...
“ Internalizar” algumas funções da ROM para o S.O. Me livrou de dependências externas Comeu uns bytes preciosos Mas viabilizou um binário único para todas as plataformas Facilitará aproveitar as extensões de memória no futuro Delegar à aplicação gerenciar o resto do hardware O S.O. identifica para você a máquina em que está rodando “ Bibliotecas” padrão no “User Space” E cada um que se vire! BASIC.SYSTEM Todo o suporte ao BASIC ficará ao cargo de uma (futura) “Aplicação” no User Space. “ Forkar” o Kernel para casos especiais Versões especializadas para cada arquitetura e/ou funcionalidade específica Versionar a API Congelar um subset mínimo da API com garantias de funcionamento em todas as versões futuras Oferecer à aplicação um mecanismo para que ela saiba o que o Kernel corrente é capaz de oferecer Gerência de Configuração to the rescue! :-)