Тема: Приклад писаної мовою FASM демки для архітектури CHIP-8
Додав до клясичного FASM`у (окрім нього існує новий форк FASM G, який взагалі не вміє кодувати жодну архітектуру) систему команд архітектури CHIP-8, всі мнемоніки cкопіював з керівництва Cowgod`а (переклад українською), єдиний суттєвий недолік цього рішення — коли програміст припускається помилки, то, інколи, асемблер не повідомляє про неї, а просто не засемблює ту мнемоніку, яка містить помилку (в майбутньому виправлю). Для додавання підримки архітектури CHIP-8 необхідно підключити заголовковий файл "chip8-arch.inc".
Моя перша демка:
В демі дракон просто махає крилами на тлі нерухомого тексту, для виводу якого уживалися як спрайтові команди, так і вбудований в CHIP-8 шрифт для шістнадцяткових чисел. Стиль кодингу демки нарочито індуський, аби початківцям було леше розібратися. Головною метою демки було знежучити заголовковий файл архітектури і показати наочно як легко додавати підтримку нової архітектури в FASM.
Один кадр демки:
В якості емуляторіа та знежучувача я послуговувався писаним мовою Go "CHIP-8, COPYRIGHT 2017 BY JEFFREY MASSUNG"
; This file adding support CHIP-8 architecture in FASM
; Written especially for replace.org.ua ukrainian coder forum
; (c) 0xDADA11C7, 2017
V0 equ 0xFFFF0
V1 equ 0xFFFF1
V2 equ 0xFFFF2
V3 equ 0xFFFF3
V4 equ 0xFFFF4
V5 equ 0xFFFF5
V6 equ 0xFFFF6
V7 equ 0xFFFF7
V8 equ 0xFFFF8
V9 equ 0xFFFF9
VA equ 0xFFFFA
VB equ 0xFFFFB
VC equ 0xFFFFC
VD equ 0xFFFFD
VE equ 0xFFFFE
VF equ 0xFFFFF
v0 equ V0
v1 equ V1
v2 equ V2
v3 equ V3
v4 equ V4
v5 equ V5
v6 equ V6
v7 equ V7
v8 equ V8
v9 equ V9
va equ VA
vb equ VB
vc equ VC
vd equ VD
ve equ VE
vf equ VF
macro cls {
db 0x00, 0xE0
}
macro ret {
db 0x00, 0xEE
}
macro sys a {
db ((a shr 0x8) and 0xf), (a and 0xff)
}
macro jp a1, a2{
if a1 = v0
db 0xB0+((a2 shr 0x8) and 0xf), a2 and 0xff
else
db 0x10+((a1 shr 0x8) and 0xf), a1 and 0xff
end if
}
macro call a {
db 0x20+((a shr 0x8) and 0xf), (a and 0xff)
}
macro se vx, a {
if ((vx >= v0) & (vx <= vf))
if ((a >= v0) & (a <= vf))
db 0x50+(vx and 0xF), (a and 0xF) shl 0x4
else
if ((a shr 8) = 0)
db 0x30+(vx and 0xF), (a and 0xFF)
else
error 'Error: [se] invalid second (8-bit constant) argument'
end if
end if
else
error 'Error: [se] invalid first (vx register) argument'
end if
}
macro sne vx, a {
if ((vx >= v0) & (vx <= vf))
if ((a >= v0) & (a <= vf))
db 0x90+(vx and 0xF), (a and 0xF) shl 0x4
else
if ((a shr 8) = 0)
db 0x40+(vx and 0xF), (a and 0xFF)
else
error 'Error: [sne] invalid second (8-bit constant) argument'
end if
end if
else
error 'Error: [sne] invalid first (vx register) argument'
end if
}
macro ld a1, a2 {
define ..defined 0
match =dt, a1 \{
if ((a2>=v0) & (a2<=vf))
db (0xF0+(a2 and 0xF)), 0x15
else
end if
define ..defined 1
\}
match =DT, a1 \{
if ((a2>=v0) & (a2<=vf))
db (0xF0+(a2 and 0xF)), 0x15
else
end if
define ..defined 1
\}
match =dt, a2 \{
if ((a1>=v0) & (a1<=vf))
db (0xF0+(a1 and 0xF)), 0x7
else
end if
define ..defined 1
\}
match =DT, a2 \{
if ((a1>=v0) & (a1<=vf))
db (0xF0+(a1 and 0xF)), 0x7
else
end if
define ..defined 1
\}
match =st, a1 \{
if ((a2>=v0) & (a2<=vf))
db (0xF0+(a2 and 0xF)), 0x18
else
end if
define ..defined 1
\}
match =ST, a1 \{
if ((a2>=v0) & (a2<=vf))
db (0xF0+(a2 and 0xF)), 0x18
else
end if
define ..defined 1
\}
match =(=I=), a1 \{
if ((a2>=v0) & (a2<=vf))
db (0xF0+(a2 and 0xF)), 0x55
end if
define ..defined 1
\}
match =(=i=), a1 \{
if ((a2>=v0) & (a2<=vf))
db (0xF0+(a2 and 0xF)), 0x55
end if
define ..defined 1
\}
match =(=I=), a2 \{
if ((a1>=v0) & (a1<=vf))
db (0xF0+(a1 and 0xF)), 0x65
end if
define ..defined 1
\}
match =(=i=), a2 \{
if ((a1>=v0) & (a1<=vf))
db (0xF0+(a1 and 0xF)), 0x65
end if
define ..defined 1
\}
match =B, a1 \{
if ((a2>=v0) & (a2<=vf))
db (0xF0+(a2 and 0xF)), 0x33
end if
define ..defined 1
\}
match =b, a1 \{
if ((a2>=v0) & (a2<=vf))
db (0xF0+(a2 and 0xF)), 0x33
end if
define ..defined 1
\}
match =F, a1 \{
if ((a2>=v0) & (a2<=vf))
db (0xF0+(a2 and 0xF)), 0x29
end if
define ..defined 1
\}
match =f, a1 \{
if ((a2>=v0) & (a2<=vf))
db (0xF0+(a2 and 0xF)), 0x29
end if
define ..defined 1
\}
;Fx0A - LD Vx, K
match =k, a2 \{
if ((a1>=v0) & (a1<=vf))
db (0xF0+(a1 and 0xF)), 0xA
end if
define ..defined 1
\}
match =K, a2 \{
if ((a1>=v0) & (a1<=vf))
db (0xF0+(a1 and 0xF)), 0xA
end if
define ..defined 1
\}
match =I, a1 \{
db 0xA0+(a2 shr 0x8), (a2 and 0xFF)
define ..defined 1
\}
if ..defined = 0
if ((a1>=v0) & (a1<=vf))
if ((a2>=v0) & (a2<=vf)))
db (0x80+(a1 and 0xF)), ((a2 and 0xF) shl 0x4)
else
db (0x60+(a1 and 0xF)), (a2 and 0xFF)
end if
end if
end if
}
macro add a1, a2 {
define ..defined 0
match =I, a1 \{
if ((a2>=v0) & (a2<=vf))
db (0xF0+(a2 and 0xF)), 0x1E
end if
define ..defined 1
\}
match =i, a1 \{
if ((a2>=v0) & (a2<=vf))
db (0xF0+(a2 and 0xF)), 0x1E
end if
define ..defined 1
\}
if (..defined = 0) & ((a1>=v0) & (a1<=vf))
if ((a2>=v0) & (a2<=vf))
db 0x80+(a1 and 0xF), ((a2 and 0xF) shl 0x4)
else
db 0x70+(a1 and 0xF), (a2 and 0xff)
end if
end if
}
macro or a1, a2 {
if ((a2>=v0) & (a2<=vf)) & ((a1>=v0) & (a1<=vf))
db 0x80+(a1 and 0xf), ((a2 and 0xf) shl 0x4)+0x1
end if
}
macro and a1, a2 {
if ((a2>=v0) & (a2<=vf)) & ((a1>=v0) & (a1<=vf))
db 0x80+(a1 and 0xf), ((a2 and 0xf) shl 0x4)+0x2
end if
}
macro xor vx, vy {
if ((vx>=v0) & (vx<=vf)) & ((vy>=v0) & (vy<=vf))
db 0x80+(vx and 0xf), ((vx and 0xf) shl 0x4)+0x3
end if
}
macro add a1, a2 {
define ..defined 0
match =I, a1 \{
if ((a2>=v0) & (a2<=vf))
db 0xF0+(a2 and 0xf), 0x1E
end if
define ..defined 1
\}
match =i, a1 \{
if ((a2>=v0) & (a2<=vf))
db 0xF0+(a2 and 0xf), 0x1E
end if
define ..defined 1
\}
if (..defined = 0) & (a1>=v0) & (a1<=vf)
if (a2>=v0) & (a2<=vf)
db 0x80+(a1 and 0xf), ((a2 and 0xf) shl 0x4)+0x4
else
db 0x70+(a1 and 0xf), a2 and 0xff
end if
end if
}
macro sub vx, vy {
if ((vx>=v0) & (vx<=vf) & (vy>=v0) & (vy<=vf))
db 0x80+(vx and 0xf), ((vy and 0xf) shl 0x4)+0x5
display 'hello'
end if
}
macro subn a1, a2 {
if ((a2>=v0) & (a2<=vf)) & ((a1>=v0) & (a1<=vf))
db 0x80+(a1 and 0xf), ((a2 and 0xf) shl 0x4)+0x7
end if
}
macro shr a1, a2 {
if ((a1>=v0) & (a1<=vf))
if a2 eq
db 0x80+(a1 and 0xf), ((a1 and 0xf) shl 0x4)+0x6
else
if (a2>=v0) & (a2<=vf)
db 0x80+(a1 and 0xf), ((a2 and 0xf) shl 0x4)+0x6
end if
end if
end if
}
macro shl a1, a2 {
if ((a1>=v0) & (a1<=vf))
if a2 eq
db 0x80+(a1 and 0xf), ((a1 and 0xf) shl 0x4)+0xE
else
if (a2>=v0) & (a2<=vf)
db 0x80+(a1 and 0xf), ((a2 and 0xf) shl 0x4)+0xE
end if
end if
end if
}
macro rnd a, b {
if (a>=v0) & (a<=vf)
db 0xC0+(a and 0xF), b and 0xFF
end if
}
macro drw vx, vy, n {
if (vx>=v0) & (vx<=vf) & (vy>=v0) & (vy<=vf) & (n <= 0xF) & (n >= 0)
db 0xD0+(vx and 0xF), ((vy and 0xF) shl 0x4)+(n and 0xF)
end if
}
macro skp vx {
if ((vx>=v0) & (vx<=vf))
db 0xE0+(vx and 0xf), 0x9E
end if
}
macro sknp vx {
if ((vx>=v0) & (vx<=vf))
db 0xE0+(vx and 0xf), 0xA1
end if
}
include 'chip8-arch.inc'
macro wait vx, hz {
local ..up, ..down
ld vx, hz
ld DT, vx
..up:
ld vx, DT
se vx, 0x0
jp ..up
}
org 0x200
start:
cls
ld V1, 0xF
ld V2, 0xA
ld V6, 0x9
ld I, msg.re
drw V2, V6, 0x5
ld I, line8
drw V2, V1, 0x1
add V2, 0x8
ld I, msg.pl
drw V2, V6, 0x5
ld I, line8
drw V2, V1, 0x1
add V2, 0x8
ld I, msg.ac
drw V2, V6, 0x5
ld I, line8
drw V2, V1, 0x1
add V2, 0x8
ld I, msg.e_dot
drw V2, V6, 0x5
ld I, line6
drw V2, V1, 0x1
add V2, 0x6
ld I, msg.or
drw V2, V6, 0x5
ld I, line8
drw V2, V1, 0x1
add V2, 0x8
ld I, msg.g_dot
drw V2, V6, 0x5
ld I, line6
drw V2, V1, 0x1
add V2, 0x7
ld I, msg.ua
drw V2, V6, 0x5
ld I, tail_end
add V2, -1
drw V2, V1, 0x6
ld V1, 0x9
ld V5, 0x1
ld V6, 0x9
ld I, dragon_body
drw V5, V6, 0x6
ld VA, V5
ld VB, V6
add VA, 0x8
add VB, 0x5
ld I, single_pixel
drw VA, VB, 0x1
add V6, -0x1
add V5, 0x4
ld V7, V5
; add V7, 0x1
ld V8, 0xA
ld V9, 0x12
ld I, msg_copyright.de
drw V8, V9, 0x4
ld I, msg_copyright.mo
add V8, 0x8
drw V8, V9, 0x4
add V8, 0xB
ld I, msg_copyright.py
drw V8, V9, 0x4
add V8, 0x8
ld I, msg_copyright.sa
drw V8, V9, 0x4
add V8, 0x8
ld I, msg_copyright.ne
drw V8, V9, 0x4
ld V8, 0x2
ld V9, 0x17
ld VA, 0x0
ld F, VA
drw V8, V9, 0x5
add V8, 0x5
ld I, msg_copyright.x
drw V8, V9, 0x5
add V8, 0x4
ld VA, 0xD
ld F, VA
drw V8, V9, 0x5
add V8, 0x5
ld VA, 0xA
ld F, VA
drw V8, V9, 0x5
add V8, 0x5
ld VA, 0xD
ld F, VA
drw V8, V9, 0x5
add V8, 0x5
ld VA, 0xA
ld F, VA
drw V8, V9, 0x5
add V8, 0x4
ld VA, 0x1
ld F, VA
drw V8, V9, 0x5
add V8, 0x4
ld VA, 0x1
ld F, VA
drw V8, V9, 0x5
add V8, 0x5
ld VA, 0xC
ld F, VA
drw V8, V9, 0x5
add V8, 0x5
ld VA, 0x7
ld F, VA
drw V8, V9, 0x5
add V9, 0x1
add V8, 0x5
ld I, msg_copyright.om1
drw V8, V9, 0x4
add V8, 0x8
ld I, msg_copyright.om2
drw V8, V9, 0x4
add V8, 0x8
wings:
ld I, dragon_wings_1
drw V5, V6, 0x5
wait V1, 20
drw V5, V6, 0x5
ld I, dragon_wings_2
drw V7, V6, 0x5
wait V1, 20
drw V7, V6, 0x5
ld I, dragon_wings_3
drw V7, V6, 0x5
wait V1, 20
drw V7, V6, 0x5
ld I, dragon_wings_4
drw V7, V6, 0x5
wait V1, 20
drw V7, V6, 0x5
ld I, dragon_wings_3
drw V7, V6, 0x5
wait V1, 20
drw V7, V6, 0x5
ld I, dragon_wings_2
drw V7, V6, 0x5
wait V1, 20
drw V7, V6, 0x5
jp wings
dragon_body:
db 0x40, 0xE0, 0x20, 0x3E, 0x1F, 0x0A
dragon_wings_1:
db 0x38, 0x70, 0xE0, 0x80, 0x00
dragon_wings_2:
db 0x00, 0x7C, 0xF8, 0xC0, 0x00
dragon_wings_3:
db 0x00, 0x00, 0x7E, 0xF8, 0x00
dragon_wings_4:
db 0x00, 0x00, 0x00, 0xFF, 0x1E
msg:
.re:
db 0xEE, 0xE8, 0xCE, 0xA8, 0xAE
.pl:
db 0xE8, 0xE8, 0x88, 0x88, 0x8E
.ac:
db 0xEE, 0xA8, 0xE8, 0xA8, 0xAE
.e_dot:
db 0xE0, 0x80, 0xE0, 0x80, 0xE8
.or:
db 0xEE, 0xAE, 0xAC, 0xAA, 0xEA
.g_dot:
db 0xF0, 0x80, 0xB0, 0x90, 0xF4
.ua:
db 0xAE, 0xAA, 0xAE, 0xAA, 0x6A
tail_end:
db 0xF0, 0x0C, 0x02, 0x22, 0x7C, 0x20
msg_copyright:
.de:
db 0xCE, 0xEC, 0xE8, 0xCE
.mo:
db 0xCE, 0xEA, 0xEA, 0xEE
.py:
db 0xEA, 0xAA, 0xAA, 0xAC
.sa:
db 0xE6, 0x8A, 0x8E, 0xEA
.ne:
db 0xAE, 0xAC, 0xE8, 0xAE
.x:
db 0xA0, 0xA0, 0x40, 0xA0, 0xA0
.om1:
db 0xB9, 0xA9, 0x2A, 0x3A
.om2:
db 0x40, 0x40, 0xA0, 0x20
single_pixel db 0x80
line8 db 0xff
line6 db 0xfc
До посту долучається архів з джерельними кодами демки і зкомпільованим бінарником replace.ch для запуску в емуляторі
chip8.7z 2.24 kb, 364 downloads since 2017-11-09