mirror of
https://github.com/KarolS/millfork.git
synced 2025-01-10 20:29:35 +00:00
Support sizeof on arrays. Preliminary Commander X16 support.
This commit is contained in:
parent
6c4dc81c1b
commit
1d445ecdd1
@ -2,12 +2,16 @@
|
||||
|
||||
## Current version
|
||||
|
||||
* `sizeof` now supports arrays.
|
||||
|
||||
* Added `-R` option for specifying extra commandline parameters for emulators.
|
||||
|
||||
* Added full 16-bit multiplication.
|
||||
|
||||
* Added preliminary support for EasyFlash.
|
||||
|
||||
* Added preliminary support for Commander X16.
|
||||
|
||||
* Allowed defining custom output padding byte value.
|
||||
|
||||
* Allowed passing non-decimal numbers to the `-D` option.
|
||||
|
@ -99,4 +99,7 @@ The compiler emits COM files.
|
||||
|
||||
* `dos_com` – a COM file for DOS on IBM PC. (very experimental)
|
||||
|
||||
* `x16_experimental` – Commander X16; very experimental,
|
||||
as both the target configuration *and* the device itself are in their experimental phases.
|
||||
|
||||
The primary and most tested platform is Commodore 64.
|
||||
|
@ -84,7 +84,7 @@ See [the ROM vs RAM guide](../api/rom-vs-ram.md) for more information.
|
||||
|
||||
* `WIDESCREEN` – 1 if the horizontal screen resolution, ignoring borders, is greater than 256, 0 otherwise
|
||||
|
||||
* `CBM` – 1 if the target is an 8-bit Commodore computer, 0 otherwise
|
||||
* `CBM` – 1 if the target is an 8-bit Commodore computer (or a compatible one), 0 otherwise
|
||||
|
||||
* `CBM_64_COMPAT` – 1 if the target is an 8-bit Commodore computer compatible with Commodore 64, 0 otherwise
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
* [Hello world](crossplatform/hello_world.mfk) (C64/C16/PET/VIC-20/PET/Atari/Apple II/BBC Micro/ZX Spectrum/PC-88/Armstrad CPC/MSX) – simple text output
|
||||
|
||||
* [Fizzbuzz](crossplatform/fizzbuzz.mfk) (C64/C16/PET/VIC-20/PET/Atari/Apple II/BBC Micro/ZX Spectrum/PC-88/Armstrad CPC/MSX) – everyone's favourite programming task
|
||||
* [Fizzbuzz](crossplatform/fizzbuzz.mfk) (C64/C16/PET/VIC-20/PET/Atari/Apple II/BBC Micro/ZX Spectrum/PC-88/Armstrad CPC/MSX/X16) – everyone's favourite programming task
|
||||
|
||||
* [Fizzbuzz 2](crossplatform/fizzbuzz2.mfk) (C64/C16/PET/VIC-20/PET/Atari/Apple II/BBC Micro/ZX Spectrum/PC-88/Armstrad CPC/MSX) – an alternative, more extensible implemententation of fizzbuzz
|
||||
|
||||
@ -61,3 +61,9 @@ how to create a program made of multiple files loaded on demand
|
||||
|
||||
* [Encoding test](msx/encoding_test.mfk) – text encoding test; displays three lines of text in three different languages,
|
||||
no more one of which will display correctly depending on the default font of your computer.
|
||||
|
||||
# Commander X16 examples
|
||||
|
||||
* [Palette](x16/palette.mfk) – displays the default 256-colour palette.
|
||||
|
||||
* [Balls](x16/palette.mfk) – 16 sprites using 240 colours.
|
||||
|
92
examples/x16/balls.mfk
Normal file
92
examples/x16/balls.mfk
Normal file
@ -0,0 +1,92 @@
|
||||
// the emulator supports only 16 sprites:
|
||||
const byte SPRITE_COUNT = 16
|
||||
array(vera_sprite_data) sprites[SPRITE_COUNT]
|
||||
array(sbyte) vx[SPRITE_COUNT]
|
||||
array(sbyte) vy[SPRITE_COUNT]
|
||||
|
||||
import random
|
||||
|
||||
void main () {
|
||||
pointer.vera_sprite_data p
|
||||
|
||||
byte i,j
|
||||
word x,y
|
||||
init_rand_seed()
|
||||
// make balls striped
|
||||
for i,0,parallelto,$1f {
|
||||
for j,1,parallelto,$f {
|
||||
sprite_bitmap[nonet(j<<5) + i] *= j
|
||||
}
|
||||
}
|
||||
for i,0,paralleluntil,SPRITE_COUNT {
|
||||
p = sprites[i].pointer
|
||||
// bitmap is at $10000:
|
||||
p->address = $800
|
||||
p->x.lo = rand()
|
||||
p->x.hi = rand() & 1
|
||||
p->y = rand()
|
||||
// no collision, above all layers, no flipping
|
||||
p->ctrl0 = $c
|
||||
// 32×32 pixels, different palette offsets
|
||||
p->ctrl1 = $a0 | (i & $f)
|
||||
vx[i] = 1 - (rand() & 2)
|
||||
vy[i] = 1 - (rand() & 2)
|
||||
}
|
||||
vera_upload_large($10000, sprite_bitmap.addr, sizeof(sprite_bitmap))
|
||||
vera_upload_large($40800, sprites.addr, sizeof(sprites))
|
||||
// enable sprites:
|
||||
vera_poke($40020, 1)
|
||||
while true {
|
||||
for i,0,paralleluntil,SPRITE_COUNT {
|
||||
p = sprites[i].pointer
|
||||
x = p->x
|
||||
y = p->y
|
||||
x += vx[i]
|
||||
y += vy[i]
|
||||
p->x = x
|
||||
p->y = y
|
||||
if x == 0 { vx[i] = 1 }
|
||||
if x >= 640-32 { vx[i] = 0-1 }
|
||||
if y == 0 { vy[i] = 1 }
|
||||
if y >= 480-32 { vy[i] = 0-1 }
|
||||
}
|
||||
vera_upload_large($40800, sprites.addr, sizeof(sprites))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
array sprite_bitmap = [
|
||||
$00,$00,$00,$00,$00,$00,$11,$11,$11,$11,$00,$00,$00,$00,$00,$00,
|
||||
$00,$00,$00,$00,$01,$11,$11,$11,$11,$11,$11,$10,$00,$00,$00,$00,
|
||||
$00,$00,$00,$01,$11,$11,$11,$11,$11,$11,$11,$11,$10,$00,$00,$00,
|
||||
$00,$00,$00,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$00,$00,$00,
|
||||
$00,$00,$01,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$10,$00,$00,
|
||||
$00,$00,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$00,$00,
|
||||
$00,$01,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$10,$00,
|
||||
$00,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$00,
|
||||
$00,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$00,
|
||||
$01,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$10,
|
||||
$01,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$10,
|
||||
$01,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$10,
|
||||
$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,
|
||||
$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,
|
||||
$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,
|
||||
$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,
|
||||
$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,
|
||||
$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,
|
||||
$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,
|
||||
$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,
|
||||
$01,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$10,
|
||||
$01,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$10,
|
||||
$01,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$10,
|
||||
$00,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$00,
|
||||
$00,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$00,
|
||||
$00,$01,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$10,$00,
|
||||
$00,$00,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$00,$00,
|
||||
$00,$00,$01,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$10,$00,$00,
|
||||
$00,$00,$00,$11,$11,$11,$11,$11,$11,$11,$11,$11,$11,$00,$00,$00,
|
||||
$00,$00,$00,$01,$11,$11,$11,$11,$11,$11,$11,$11,$10,$00,$00,$00,
|
||||
$00,$00,$00,$00,$01,$11,$11,$11,$11,$11,$11,$10,$00,$00,$00,$00,
|
||||
$00,$00,$00,$00,$00,$00,$11,$11,$11,$11,$00,$00,$00,$00,$00,$00
|
||||
]
|
||||
|
24
examples/x16/palette.mfk
Normal file
24
examples/x16/palette.mfk
Normal file
@ -0,0 +1,24 @@
|
||||
void main() {
|
||||
word i
|
||||
byte hn, ln
|
||||
// 256-colour text mode for layer 0
|
||||
vera_poke($40000, $21)
|
||||
// 8×8 tiles, 64×64 tile map
|
||||
vera_poke($40001, $35)
|
||||
// 2× zoom in
|
||||
vera_poke($40041, $40)
|
||||
vera_poke($40042, $40)
|
||||
i = 0
|
||||
while i < $2000 {
|
||||
vera_poke(i, $A0)
|
||||
if i.lo & $7f < 64 {
|
||||
ln = lo(i>>1) & $1f
|
||||
hn = lo(i>>2) & $e0
|
||||
vera_poke(i+1, hn | ln)
|
||||
} else {
|
||||
vera_poke(i+1, 0)
|
||||
}
|
||||
i += 2
|
||||
}
|
||||
while true {}
|
||||
}
|
40
include/x16_experimental.ini
Normal file
40
include/x16_experimental.ini
Normal file
@ -0,0 +1,40 @@
|
||||
; Commander X16
|
||||
; VERY EXPERIMENTAL
|
||||
; The device's haven't been completed yet, so this platform configuration may not run on the final device
|
||||
; Use only for goofing around plz
|
||||
|
||||
[compilation]
|
||||
arch=cmos
|
||||
encoding=petscii
|
||||
screen_encoding=petscr
|
||||
modules=loader_0801,c64_kernal,x16_hardware,c64_panic,stdlib
|
||||
|
||||
[allocation]
|
||||
; list of free zp pointer locations is the same as C64
|
||||
zp_pointers=$FB,$FD,$43,$45,$47,$4B,$F7,$F9,$9E,$9B,$3D
|
||||
segments=default,himem0
|
||||
default_code_segment=default
|
||||
segment_default_start=$80D
|
||||
segment_default_codeend=$9eff
|
||||
segment_default_datastart=after_code
|
||||
segment_default_end=$9eff
|
||||
|
||||
segment_himem0_start=$c000
|
||||
segment_himem0_codeend=$dfff
|
||||
segment_himem0_datastart=after_code
|
||||
segment_himem0_end=$dfff
|
||||
|
||||
[define]
|
||||
CBM=1
|
||||
WIDESCREEN=1
|
||||
KEYBOARD=1
|
||||
JOYSTICKS=0
|
||||
HAS_BITMAP_MODE=1
|
||||
|
||||
[output]
|
||||
style=single
|
||||
format=startaddr,allocated
|
||||
extension=prg
|
||||
labels=vice
|
||||
|
||||
|
103
include/x16_hardware.mfk
Normal file
103
include/x16_hardware.mfk
Normal file
@ -0,0 +1,103 @@
|
||||
// TODO: bankswitching
|
||||
|
||||
|
||||
volatile byte vera_addr_hi @ $9f20
|
||||
volatile byte vera_addr_mi @ $9f21
|
||||
volatile byte vera_addr_lo @ $9f22
|
||||
volatile byte vera_data1 @ $9f23
|
||||
volatile byte vera_data2 @ $9f24
|
||||
volatile byte vera_ctrl @ $9f25
|
||||
volatile byte vera_ien @ $9f26
|
||||
volatile byte vera_isr @ $9f27
|
||||
|
||||
struct vera_layer_setup {
|
||||
byte ctrl0
|
||||
byte ctrl1
|
||||
word map_base
|
||||
word tile_base
|
||||
word hscroll
|
||||
word vscroll
|
||||
}
|
||||
|
||||
asm void set_vera_layer_internal(pointer.vera_layer_setup ax, byte y) {
|
||||
sta __reg
|
||||
stx __reg+1
|
||||
stz vera_ctrl
|
||||
lda $14
|
||||
sta vera_addr_hi
|
||||
stz vera_addr_mi
|
||||
sty vera_addr_lo
|
||||
ldy #0
|
||||
__set_layer_internal_loop:
|
||||
lda (__reg),y
|
||||
sta vera_data1
|
||||
iny
|
||||
cpy #sizeof(vera_layer_setup)
|
||||
bne __set_layer_internal_loop
|
||||
? rts
|
||||
}
|
||||
|
||||
asm void set_vera_layer0(pointer.vera_layer_setup ax) {
|
||||
? ldy #0
|
||||
? jmp set_vera_layer_internal
|
||||
}
|
||||
|
||||
asm void set_vera_layer1(pointer.vera_layer_setup ax) {
|
||||
? ldy #0
|
||||
? jmp set_vera_layer_internal
|
||||
}
|
||||
|
||||
inline void vera_poke(int24 address, byte value) {
|
||||
vera_addr_lo = address.b0
|
||||
vera_addr_mi = address.b1
|
||||
vera_addr_hi = address.b2
|
||||
vera_ctrl = 0
|
||||
vera_data1 = value
|
||||
}
|
||||
|
||||
inline void vera_fill(int24 address, byte value, word size) {
|
||||
word i
|
||||
vera_addr_lo = address.b0
|
||||
vera_addr_mi = address.b1
|
||||
vera_addr_hi = address.b2 | $10
|
||||
vera_ctrl = 0
|
||||
for i,0,paralleluntil,size {
|
||||
vera_data1 = value
|
||||
}
|
||||
}
|
||||
|
||||
void vera_upload_large(int24 address, pointer source, word size) {
|
||||
word i
|
||||
vera_ctrl = 0
|
||||
vera_addr_lo = address.b0
|
||||
vera_addr_mi = address.b1
|
||||
vera_addr_hi = address.b2 | $10
|
||||
for i,0,paralleluntil,size {
|
||||
vera_data1 = source[i]
|
||||
}
|
||||
}
|
||||
|
||||
inline void vera_upload(int24 address, pointer source, byte size) {
|
||||
byte i
|
||||
vera_ctrl = 0
|
||||
vera_addr_lo = address.b0
|
||||
vera_addr_mi = address.b1
|
||||
vera_addr_hi = address.b2 | $10
|
||||
asm {
|
||||
? ldy #0
|
||||
__vera_upload_loop:
|
||||
? lda (__reg),y
|
||||
? sta vera_data1
|
||||
? iny
|
||||
? cpy size
|
||||
? bne __vera_upload_loop
|
||||
}
|
||||
}
|
||||
|
||||
struct vera_sprite_data {
|
||||
word address
|
||||
word x
|
||||
word y
|
||||
byte ctrl0
|
||||
byte ctrl1
|
||||
}
|
@ -599,8 +599,8 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
||||
case Some(thing) => thing match {
|
||||
case t: Type => t.size
|
||||
case v: Variable => v.typ.size
|
||||
case a: InitializedArray => a.elementType.size * a.contents.length
|
||||
case a: UninitializedArray => a.sizeInBytes
|
||||
case a: MfArray => a.sizeInBytes
|
||||
case ConstantThing(_, MemoryAddressConstant(a: MfArray), _) => a.sizeInBytes
|
||||
case x =>
|
||||
log.error("Invalid parameter for expr: " + name)
|
||||
1
|
||||
|
Loading…
x
Reference in New Issue
Block a user