1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-06-02 00:41:40 +00:00

Merge pull request #66 from zbyti/master

Atari 800 System Off example, some minor refactor and more examples
This commit is contained in:
Karol Stasiak 2020-09-17 16:01:00 +02:00 committed by GitHub
commit fe094af912
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 245 additions and 12 deletions

View File

@ -82,10 +82,14 @@ how to create a program made of multiple files loaded on demand
* [Rainbow example](a8/rainbow.mfk) simple scrolling rasterbars
* [DLI example](a8/dli-example.mfk) simple display list and display list interrupt example
* [DLI example](a8/dli_example.mfk) simple display list and display list interrupt example
* [Scroll example](a8/endless_scroll.mfk) simple horizontal scroll example
* [System Off example](a8/systemoff_example.mfk) Programming example with ROM off
* [GR.8 Chessboard Benchmark](a8/gr8_chessboard_benchmark.mfk) Chessboard drawing benchmark in GR.0
## Game Boy examples
* [GB test example](gb/gbtest.mfk) a partial port of the NES example, with a rudimentary experimental text output implementation

View File

@ -4,7 +4,7 @@ const word dliAddr = $3100
const array(byte) dl @ dlAddr = [
$70,$70,$70,
$42,$00,$40,2,2,2,2,$f0,2,2,2,2,
$41,lo(dlAddr),hi(dlAddr)
$41,@word[dlAddr]
]
volatile word SDLST @ $230

View File

@ -3,22 +3,20 @@ const word lms1Addr = $4000
const word lms2Addr = $4060
const word lms3Addr = $40c0
volatile word SDLST @ $230
array(byte) dl @ dlAddr = [
$70,$70,$70,
$52,lo(lms1Addr),hi(lms1Addr),
$52,lo(lms2Addr),hi(lms2Addr),
$52,lo(lms3Addr),hi(lms3Addr),
$52, @word[lms1Addr],
$52, @word[lms2Addr],
$52, @word[lms3Addr],
$41,lo(dlAddr),hi(dlAddr)
]
noinline asm void wait(byte register(a) f) {
clc
adc os_RTCLOK+2
rt_check:
cmp os_RTCLOK+2
bne rt_check
adc os_RTCLOK.b2
.rt_check:
cmp os_RTCLOK.b2
bne .rt_check
rts
}
@ -33,7 +31,7 @@ void main() {
screeni = lms1Addr
wait(1)
SDLST = dl.addr
os_SDLST = dl.addr
while true {
if hscroli == $b {

View File

@ -0,0 +1,109 @@
const word lmsAddr1 = $8400
const word lmsAddr2 = $6010
byte i@$e0, j@$e2, k@$e4, count@$e6
pointer screen@$e8
const array(byte) dl align(256) = [
$70,$70,$70,
$4f,@word[lmsAddr2],
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,
$4f,0,lmsAddr2.hi + $10,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,
$41,@word[dl.addr]
]
const array(byte) dlPrint align(16) = [
$70,$70,$70,
$42,@word[lmsAddr1],
$41,@word[dlPrint.addr]
]
asm void pause() {
LDA os_RTCLOK.b2
.rt_check:
CMP os_RTCLOK.b2
BEQ .rt_check
RTS
}
//print HEX value
void printScore() {
array(byte) tmp[2]
byte iter
screen = lmsAddr1
os_SDLST = dlPrint.addr
tmp[0] = count >> 4
tmp[1] = count & %00001111
for iter:tmp {
if tmp[iter] < 10 {
screen[iter] = tmp[iter] + $10
} else {
screen[iter] = tmp[iter] + $17
}
}
}
void drawBoard() {
screen = lmsAddr2
os_SDLST = dl.addr
for i,7,downto,0 {
for j,23,downto,0 {
for k,3,downto,0 {
screen[0] = 255
screen[1] = 255
screen[2] = 255
screen += 6
}
screen += 16
}
if (i & 1) != 0 {
screen += 3
} else {
screen -= 3
}
}
}
void main() {
count = 0
pause()
os_RTCLOK.b2 = 0
while os_RTCLOK.b2 < 150 {
drawBoard()
count += 1
}
printScore()
while (true){}
}

View File

@ -0,0 +1,122 @@
// ================================================
//
// antic_nmien = $40
//
// %01000000 $40 VBI
// %10000000 $80 DLI
// %11000000 $c0 VBI + DLI
//
// ================================================
//
// pia_portb = $fe
//
// PORTB_BASIC_OFF + PORTB_SELFTEST_OFF + %01111100
//
// PORTB_SELFTEST_OFF = %10000000; portb bit value to turn Self-Test off
// PORTB_BASIC_OFF = %00000010; portb bit value to turn Basic off
// PORTB_SYSTEM_ON = %00000001; portb bit value to turn System on
//
// ================================================
byte nmien = $c0
byte rti @ $15 // default routine for VBI & DLI
word vbivec @ $10 // vector for VBI
word vdslst @ $16 // vector for DLI
// simple display list; LMS = $e000
const array(byte) dl align(32) = [
$70,$70,$70,
$42,$00,$e0,2,2,$f0,2,2,2,$f0,2,2,2,
$41,@word[dl.addr]
]
// init procedure
void system_off(){
asm { sei } // turn off IRQ
antic_nmien = 0 // turn off ANTIC
pia_portb = $fe // turn off ROM
rti = $40 // set RTI opcode
vbivec = rti.addr // set address for VBI routine
vdslst = rti.addr // set address for DLI routine
os_NMIVEC = nmi.addr // set address for custom NMI handler
antic_nmien = nmien
}
// custom NMI handler
asm void nmi(){
bit antic_nmist // test nmist
bpl .vblclock // if 7-bit not set handle VBI
jmp (vdslst) // indirect jump to DLI routine
.vblclock: // RTCLOK maintainer
inc os_RTCLOK.b2
bne .tickend
inc os_RTCLOK.b1
bne .tickend
inc os_RTCLOK.b0
.tickend:
jmp (vbivec) // indirect jump to VBI routine
}
// example dli
interrupt asm void dli_first(){
pha
lda #$2a
sta gtia_colpf2
sta antic_wsync
lda #<dli_second.addr
sta vdslst.lo
lda #>dli_second.addr
sta vdslst.hi
pla
rti
}
// example dli
interrupt void dli_second(){
gtia_colpf2 = $de
antic_wsync = $de
vdslst = dli_first.addr
}
// wait for VBLANK
asm void pause() {
lda os_RTCLOK.b2
.rt_check:
cmp os_RTCLOK.b2
beq .rt_check
rts
}
// wait 0-255 frames
noinline asm void wait(byte register(a) f) {
clc
adc os_RTCLOK.b2
.rt_check:
cmp os_RTCLOK.b2
bne .rt_check
rts
}
// example vbi
interrupt void vbi(){
gtia_colpf2 = os_RTCLOK.b2
}
// main procedure
void main(){
system_off() // turn off OS
wait(100) // waint 2 sec on PAL for fun
antic_dlist = dl.addr // set custom display list
wait(100) // waint 2 sec on PAL for the lulz
vbivec = vbi.addr // set custom VBI
wait(100) // waint 2 sec on PAL because we can
vdslst = dli_first.addr // set custom DLI
while(true){
wait(100)
nmien ^= %10000000 // toggle DLI
antic_nmien = nmien
}
}