From e8a50dc610522e8ba7698e0694202fba716ab8b9 Mon Sep 17 00:00:00 2001 From: zbyti <zbyti@yahoo.com> Date: Wed, 16 Sep 2020 12:04:39 +0200 Subject: [PATCH] A8 system off example and some minor refactor --- examples/README.md | 4 +- .../a8/{dli-example.mfk => dli_example.mfk} | 0 examples/a8/systemoff_example.mfk | 129 ++++++++++++++++++ 3 files changed, 132 insertions(+), 1 deletion(-) rename examples/a8/{dli-example.mfk => dli_example.mfk} (100%) create mode 100644 examples/a8/systemoff_example.mfk diff --git a/examples/README.md b/examples/README.md index 56e4340d..4b127cf4 100644 --- a/examples/README.md +++ b/examples/README.md @@ -82,10 +82,12 @@ 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 + ## Game Boy examples * [GB test example](gb/gbtest.mfk) – a partial port of the NES example, with a rudimentary experimental text output implementation diff --git a/examples/a8/dli-example.mfk b/examples/a8/dli_example.mfk similarity index 100% rename from examples/a8/dli-example.mfk rename to examples/a8/dli_example.mfk diff --git a/examples/a8/systemoff_example.mfk b/examples/a8/systemoff_example.mfk new file mode 100644 index 00000000..80fda4aa --- /dev/null +++ b/examples/a8/systemoff_example.mfk @@ -0,0 +1,129 @@ +// ================================================ +// +// 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 asm void dli_second(){ + pha + lda #$de + sta gtia_colpf2 + sta antic_wsync + lda #<dli_first.addr + sta vdslst.lo + lda #>dli_first.addr + sta vdslst.hi + pla + rti +} + +// 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 procdure +void main(){ + system_off(); // turn off OS + + wait(100) // waint 2 sec on PAL for fun + antic_dlist = dl.addr // set custom displaylist + 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 + } +}