// Libthomson - C wrapper for Thomson MO/TO monitor and hardware // Copyright 2012-2013, Adrien Destugues // // This file is distributed under the terms of the MIT licence. // You need the GCC-6809 compiler based on lwtools to use this file. // http://www.boxofdoom.net/2011/09/22/how-to-compile-gcc-for-the-6809-processor-gcc6809/ #pragma once // 5 : MO5 / 8: TO8 #ifndef PLATFORM #error "make TARGET=TO8 or make TARGET=MO5" #endif /////////////////////////////////////// // THOMSON.H /////////////////////////////////////// /* MONITOR ZERO-PAGE */ struct Monitor { unsigned char TERMIN[0x18]; unsigned char STATUS; unsigned char TABPT; unsigned char RANG; unsigned char COLN; unsigned char TOPTAB; unsigned char TOPRAN; unsigned char BOTTAB; unsigned char BOTRAN; unsigned int SCRPT; unsigned int STADR; unsigned int ENDDR; unsigned int BLOCZ; unsigned char FORME; unsigned char ATRANG; unsigned char COLOUR; unsigned char PAGFLG; unsigned char SCROLS; unsigned char CURSFL; unsigned char COPCHR; unsigned char EFCMPT; unsigned char ITCMPT; unsigned int PLOTX; unsigned int PLOTY; unsigned char CHDRAW; unsigned char KEY; unsigned char CMPKB; unsigned char _unused1; unsigned char TEMPO; unsigned char _unused2; unsigned char DUREE; unsigned char WAVE; unsigned int OCTAVE; unsigned char K7DATA; unsigned char K7LENG; unsigned char PROPC; unsigned char PRSTA; unsigned int TEMP; unsigned int SAVEST; unsigned char DKOPC; unsigned char DKDRV; unsigned int DKTRK; unsigned char DKSEC; unsigned char DKNUM; unsigned char DKSTA; unsigned int DKBUF; unsigned char DKTRACK[8]; unsigned char SEQUCE; unsigned char US1; unsigned char ACCENT; unsigned char SS2GET; unsigned char SS3GET; unsigned int SWIPT; unsigned char _unused3; unsigned int TIMEPT; unsigned char SEMIRQ; unsigned int IRQPT; unsigned char _unused4; unsigned int FIRQPT; unsigned char _unused5; unsigned int SIMUL; unsigned char _unused6; unsigned int CHRPTR; unsigned char _unused7; unsigned int USERAF; unsigned char _unused8; unsigned int GENPTR; unsigned char _unused9; unsigned char LATCLV; unsigned char GRCODE; unsigned char DECALG; unsigned char _unusedA[6]; unsigned char DEFDST; unsigned char DKFLG; }; _Static_assert(sizeof(Monitor) == 0x80, "Problem with struct packing, Monitor Zero-Page has wrong size."); void printhex(unsigned char i); extern unsigned char mark[]; /* HARDWARE */ #define FDC_STATUS (*(volatile unsigned char*)(FDCBASE)) //////////////////////////////////////// // MO5.H //////////////////////////////////////// #if PLATFORM == 5 /***************************************************************************** * MOx CODE ****************************************************************************/ volatile Monitor* monitor = (volatile Monitor*)0x2000; #define FDCBASE 0xA7D0 /* MONITOR ENTRY POINTS */ static inline void MENU() { asm(" SWI \n" " FCB 0" ); } static inline void PUTC(unsigned char car) { asm(" swi \n" " fcb 2" ::"B" (car) ); } static inline void FRM0() { asm(" SWI \n" " FCB 4" ); } static inline void FRM1() { asm(" SWI \n" " FCB 6" ); } static inline void BEEP() { asm(" SWI \n" " FCB 8" ); } // TODO GETC and KTST return values in B,A and Z-flag. How to get these // back in C ? static inline void DRAW(int x, int y) { asm(" SWI \n" " FCB 0xE" :: "X" (x), "Y" (y) ); } static inline void PLOT(int x, int y) { asm(" SWI \n" " FCB 0x10" :: "X" (x), "Y" (y) ); } static inline void CHPL(int x, int y) { asm(" SWI \n" " FCB 0x12" :: "X" (x), "Y" (y) ); } // TODO GETP returns in B, LPIN in flag C, GETL flag C and regs XY // GETS and JOYS in A enum Note { DO = 0, DOs = 1, RE = 2, REs = 3, MI = 4, FA = 5, FAs = 6, SO = 7, SOs = 8, LA = 9, LAs = 9, SI = 10, UT = 11, // TODO what happens with other values ? }; static inline void NOTE(enum Note note) { asm(" SWI \n" " FCB 0x1E" :: "B" (note) ); } /* FLOPPY DRIVE MONITOR ROM */ // NOTE DKOPC was split into several commands to make it easier to use from // C code. static inline void write(unsigned char track, unsigned char sector, unsigned char* buffer) { DKTRK = (unsigned char)track; DKSEC = (unsigned char)sector; DKOPC = 8; DKBUF = (unsigned int)buffer; asm(" swi \n" " fcb 0x26" ); } static inline void read(unsigned char track, unsigned char sector, unsigned char* output) { for(;;) { DKTRK = (unsigned char)track; DKSEC = (unsigned char)sector; DKOPC = 2; DKBUF = (unsigned int)output; asm(" swi \n" " fcb 0x26" ); if (DKSTA == 0x44 || DKSTA == 0) return; // Sector read ok! printhex(DKSTA); } } static inline void BOOT() { asm(" SWI \n" " FCB 0x28" ); } #else /***************************************************************************** * TOx CODE ****************************************************************************/ /* MONITOR ENTRY POINTS */ #define mon_putc(car) { \ asm("JSR \t0xE803 \t; TO8 PUTC\n"\ ::"B" ((unsigned char) (car))\ ); \ } volatile Monitor* monitor = (volatile Monitor*)0x6000; #define write(track, sector, buffer) {\ DKTRK = (unsigned char)track;\ DKSEC = (unsigned char)sector;\ DKOPC = 8;\ DKBUF = (unsigned int)buffer;\ \ asm("JSR \t 0xE004 \t; TO8 DKCONT\n"\ ); \ } /* FLOPPY DRIVE MONITOR ROM */ inline void read(unsigned char track, unsigned char sector, unsigned char* output) { for(;;) { DKTRK = (unsigned char)track; DKSEC = (unsigned char)sector; DKOPC = 2; DKBUF = (unsigned int)output; asm("JSR \t 0xE004 \t \n"); \ if (DKSTA == 0x44 || DKSTA == 0) return; // Sector read ok! printhex(DKSTA); } } #endif