/*>r6502main.c
 *
 * BBC 6502 to RISC OS library code
 * by Michael Foot.
 * Version 1.03 (16 Jun 2001).
 *
 */

/*#define __JMP_BUF_SIZE 100*/

/*#include <setjmp.h>*/
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "kernel.h"
#include "swis.h"

#include "r6502lib.h"

#define MODE12_X 320 /*mode 12 is 320 pixels wide*/
#define MODE12_Y 256

/*int a76489_lookup[0x400] =
{
0x0000,0xBEE7,0xAEE7,0xA58B,0x9EE7,0x99C1,0x958B,0x91FC,
0x8EE7,0x8C2F,0x89C1,0x878D,0x858B,0x83B2,0x81FC,0x8065,
0x7EE7,0x7D81,0x7C2F,0x7AF0,0x79C1,0x78A0,0x778D,0x7687,
0x758B,0x749A,0x73B2,0x72D3,0x71FC,0x712D,0x7065,0x6FA3,
0x6EE7,0x6E31,0x6D81,0x6CD6,0x6C2F,0x6B8D,0x6AF0,0x6A56,
0x69C1,0x692F,0x68A0,0x6815,0x678D,0x6709,0x6687,0x6608,
0x658B,0x6511,0x649A,0x6425,0x63B2,0x6342,0x62D3,0x6267,
0x61FC,0x6194,0x612D,0x60C8,0x6065,0x6003,0x5FA3,0x5F44,
0x5EE7,0x5E8C,0x5E31,0x5DD9,0x5D81,0x5D2B,0x5CD6,0x5C82,
0x5C2F,0x5BDE,0x5B8D,0x5B3E,0x5AF0,0x5AA2,0x5A56,0x5A0B,
0x59C1,0x5977,0x592F,0x58E7,0x58A0,0x585A,0x5815,0x57D1,
0x578D,0x574B,0x5709,0x56C7,0x5687,0x5647,0x5608,0x55C9,
0x558B,0x554E,0x5511,0x54D5,0x549A,0x545F,0x5425,0x53EB,
0x53B2,0x537A,0x5342,0x530A,0x52D3,0x529D,0x5267,0x5231,
0x51FC,0x51C8,0x5194,0x5160,0x512D,0x50FA,0x50C8,0x5096,
0x5065,0x5034,0x5003,0x4FD3,0x4FA3,0x4F73,0x4F44,0x4F16,
0x4EE7,0x4EB9,0x4E8C,0x4E5E,0x4E31,0x4E05,0x4DD9,0x4DAD,
0x4D81,0x4D56,0x4D2B,0x4D00,0x4CD6,0x4CAC,0x4C82,0x4C58,
0x4C2F,0x4C06,0x4BDE,0x4BB5,0x4B8D,0x4B65,0x4B3E,0x4B17,
0x4AF0,0x4AC9,0x4AA2,0x4A7C,0x4A56,0x4A30,0x4A0B,0x49E6,
0x49C1,0x499C,0x4977,0x4953,0x492F,0x490B,0x48E7,0x48C4,
0x48A0,0x487D,0x485A,0x4838,0x4815,0x47F3,0x47D1,0x47AF,
0x478D,0x476C,0x474B,0x4729,0x4709,0x46E8,0x46C7,0x46A7,
0x4687,0x4667,0x4647,0x4627,0x4608,0x45E8,0x45C9,0x45AA,
0x458B,0x456D,0x454E,0x4530,0x4511,0x44F3,0x44D5,0x44B8,
0x449A,0x447C,0x445F,0x4442,0x4425,0x4408,0x43EB,0x43CF,
0x43B2,0x4396,0x437A,0x435E,0x4342,0x4326,0x430A,0x42EF,
0x42D3,0x42B8,0x429D,0x4282,0x4267,0x424C,0x4231,0x4217,
0x41FC,0x41E2,0x41C8,0x41AE,0x4194,0x417A,0x4160,0x4146,
0x412D,0x4113,0x40FA,0x40E1,0x40C8,0x40AF,0x4096,0x407D,
0x4065,0x404C,0x4034,0x401B,0x4003,0x3FEB,0x3FD3,0x3FBB,
0x3FA3,0x3F8B,0x3F73,0x3F5C,0x3F44,0x3F2D,0x3F16,0x3EFE,
0x3EE7,0x3ED0,0x3EB9,0x3EA2,0x3E8C,0x3E75,0x3E5E,0x3E48,
0x3E31,0x3E1B,0x3E05,0x3DEF,0x3DD9,0x3DC2,0x3DAD,0x3D97,
0x3D81,0x3D6B,0x3D56,0x3D40,0x3D2B,0x3D15,0x3D00,0x3CEB,
0x3CD6,0x3CC1,0x3CAC,0x3C97,0x3C82,0x3C6D,0x3C58,0x3C44,
0x3C2F,0x3C1B,0x3C06,0x3BF2,0x3BDE,0x3BC9,0x3BB5,0x3BA1,
0x3B8D,0x3B79,0x3B65,0x3B52,0x3B3E,0x3B2A,0x3B17,0x3B03,
0x3AF0,0x3ADC,0x3AC9,0x3AB6,0x3AA2,0x3A8F,0x3A7C,0x3A69,
0x3A56,0x3A43,0x3A30,0x3A1E,0x3A0B,0x39F8,0x39E6,0x39D3,
0x39C1,0x39AE,0x399C,0x3989,0x3977,0x3965,0x3953,0x3941,
0x392F,0x391D,0x390B,0x38F9,0x38E7,0x38D5,0x38C4,0x38B2,
0x38A0,0x388F,0x387D,0x386C,0x385A,0x3849,0x3838,0x3826,
0x3815,0x3804,0x37F3,0x37E2,0x37D1,0x37C0,0x37AF,0x379E,
0x378D,0x377D,0x376C,0x375B,0x374B,0x373A,0x3729,0x3719,
0x3709,0x36F8,0x36E8,0x36D8,0x36C7,0x36B7,0x36A7,0x3697,
0x3687,0x3677,0x3667,0x3657,0x3647,0x3637,0x3627,0x3617,
0x3608,0x35F8,0x35E8,0x35D9,0x35C9,0x35BA,0x35AA,0x359B,
0x358B,0x357C,0x356D,0x355D,0x354E,0x353F,0x3530,0x3520,
0x3511,0x3502,0x34F3,0x34E4,0x34D5,0x34C6,0x34B8,0x34A9,
0x349A,0x348B,0x347C,0x346E,0x345F,0x3451,0x3442,0x3433,
0x3425,0x3416,0x3408,0x33FA,0x33EB,0x33DD,0x33CF,0x33C0,
0x33B2,0x33A4,0x3396,0x3388,0x337A,0x336C,0x335E,0x3350,
0x3342,0x3334,0x3326,0x3318,0x330A,0x32FC,0x32EF,0x32E1,
0x32D3,0x32C6,0x32B8,0x32AA,0x329D,0x328F,0x3282,0x3274,
0x3267,0x3259,0x324C,0x323F,0x3231,0x3224,0x3217,0x3209,
0x31FC,0x31EF,0x31E2,0x31D5,0x31C8,0x31BB,0x31AE,0x31A1,
0x3194,0x3187,0x317A,0x316D,0x3160,0x3153,0x3146,0x313A,
0x312D,0x3120,0x3113,0x3107,0x30FA,0x30EE,0x30E1,0x30D4,
0x30C8,0x30BB,0x30AF,0x30A2,0x3096,0x308A,0x307D,0x3071,
0x3065,0x3058,0x304C,0x3040,0x3034,0x3027,0x301B,0x300F,
0x3003,0x2FF7,0x2FEB,0x2FDF,0x2FD3,0x2FC7,0x2FBB,0x2FAF,
0x2FA3,0x2F97,0x2F8B,0x2F7F,0x2F73,0x2F68,0x2F5C,0x2F50,
0x2F44,0x2F39,0x2F2D,0x2F21,0x2F16,0x2F0A,0x2EFE,0x2EF3,
0x2EE7,0x2EDC,0x2ED0,0x2EC5,0x2EB9,0x2EAE,0x2EA2,0x2E97,
0x2E8C,0x2E80,0x2E75,0x2E6A,0x2E5E,0x2E53,0x2E48,0x2E3D,
0x2E31,0x2E26,0x2E1B,0x2E10,0x2E05,0x2DFA,0x2DEF,0x2DE4,
0x2DD9,0x2DCD,0x2DC2,0x2DB8,0x2DAD,0x2DA2,0x2D97,0x2D8C,
0x2D81,0x2D76,0x2D6B,0x2D60,0x2D56,0x2D4B,0x2D40,0x2D35,
0x2D2B,0x2D20,0x2D15,0x2D0B,0x2D00,0x2CF5,0x2CEB,0x2CE0,
0x2CD6,0x2CCB,0x2CC1,0x2CB6,0x2CAC,0x2CA1,0x2C97,0x2C8C,
0x2C82,0x2C77,0x2C6D,0x2C63,0x2C58,0x2C4E,0x2C44,0x2C39,
0x2C2F,0x2C25,0x2C1B,0x2C10,0x2C06,0x2BFC,0x2BF2,0x2BE8,
0x2BDE,0x2BD4,0x2BC9,0x2BBF,0x2BB5,0x2BAB,0x2BA1,0x2B97,
0x2B8D,0x2B83,0x2B79,0x2B6F,0x2B65,0x2B5C,0x2B52,0x2B48,
0x2B3E,0x2B34,0x2B2A,0x2B20,0x2B17,0x2B0D,0x2B03,0x2AF9,
0x2AF0,0x2AE6,0x2ADC,0x2AD3,0x2AC9,0x2ABF,0x2AB6,0x2AAC,
0x2AA2,0x2A99,0x2A8F,0x2A86,0x2A7C,0x2A73,0x2A69,0x2A60,
0x2A56,0x2A4D,0x2A43,0x2A3A,0x2A30,0x2A27,0x2A1E,0x2A14,
0x2A0B,0x2A02,0x29F8,0x29EF,0x29E6,0x29DC,0x29D3,0x29CA,
0x29C1,0x29B7,0x29AE,0x29A5,0x299C,0x2993,0x2989,0x2980,
0x2977,0x296E,0x2965,0x295C,0x2953,0x294A,0x2941,0x2938,
0x292F,0x2926,0x291D,0x2914,0x290B,0x2902,0x28F9,0x28F0,
0x28E7,0x28DE,0x28D5,0x28CC,0x28C4,0x28BB,0x28B2,0x28A9,
0x28A0,0x2897,0x288F,0x2886,0x287D,0x2874,0x286C,0x2863,
0x285A,0x2852,0x2849,0x2840,0x2838,0x282F,0x2826,0x281E,
0x2815,0x280D,0x2804,0x27FC,0x27F3,0x27EA,0x27E2,0x27D9,
0x27D1,0x27C8,0x27C0,0x27B7,0x27AF,0x27A7,0x279E,0x2796,
0x278D,0x2785,0x277D,0x2774,0x276C,0x2764,0x275B,0x2753,
0x274B,0x2742,0x273A,0x2732,0x2729,0x2721,0x2719,0x2711,
0x2709,0x2700,0x26F8,0x26F0,0x26E8,0x26E0,0x26D8,0x26CF,
0x26C7,0x26BF,0x26B7,0x26AF,0x26A7,0x269F,0x2697,0x268F,
0x2687,0x267F,0x2677,0x266F,0x2667,0x265F,0x2657,0x264F,
0x2647,0x263F,0x2637,0x262F,0x2627,0x261F,0x2617,0x260F,
0x2608,0x2600,0x25F8,0x25F0,0x25E8,0x25E0,0x25D9,0x25D1,
0x25C9,0x25C1,0x25BA,0x25B2,0x25AA,0x25A2,0x259B,0x2593,
0x258B,0x2584,0x257C,0x2574,0x256D,0x2565,0x255D,0x2556,
0x254E,0x2546,0x253F,0x2537,0x2530,0x2528,0x2520,0x2519,
0x2511,0x250A,0x2502,0x24FB,0x24F3,0x24EC,0x24E4,0x24DD,
0x24D5,0x24CE,0x24C6,0x24BF,0x24B8,0x24B0,0x24A9,0x24A1,
0x249A,0x2493,0x248B,0x2484,0x247C,0x2475,0x246E,0x2466,
0x245F,0x2458,0x2451,0x2449,0x2442,0x243B,0x2433,0x242C,
0x2425,0x241E,0x2416,0x240F,0x2408,0x2401,0x23FA,0x23F2,
0x23EB,0x23E4,0x23DD,0x23D6,0x23CF,0x23C8,0x23C0,0x23B9,
0x23B2,0x23AB,0x23A4,0x239D,0x2396,0x238F,0x2388,0x2381,
0x237A,0x2373,0x236C,0x2365,0x235E,0x2357,0x2350,0x2349,
0x2342,0x233B,0x2334,0x232D,0x2326,0x231F,0x2318,0x2311,
0x230A,0x2303,0x22FC,0x22F5,0x22EF,0x22E8,0x22E1,0x22DA,
0x22D3,0x22CC,0x22C6,0x22BF,0x22B8,0x22B1,0x22AA,0x22A4,
0x229D,0x2296,0x228F,0x2288,0x2282,0x227B,0x2274,0x226D,
0x2267,0x2260,0x2259,0x2253,0x224C,0x2245,0x223F,0x2238,
0x2231,0x222B,0x2224,0x221D,0x2217,0x2210,0x2209,0x2203,
0x21FC,0x21F6,0x21EF,0x21E9,0x21E2,0x21DB,0x21D5,0x21CE,
0x21C8,0x21C1,0x21BB,0x21B4,0x21AE,0x21A7,0x21A1,0x219A,
0x2194,0x218D,0x2187,0x2180,0x217A,0x2173,0x216D,0x2167,
0x2160,0x215A,0x2153,0x214D,0x2146,0x2140,0x213A,0x2133,
0x212D,0x2127,0x2120,0x211A,0x2113,0x210D,0x2107,0x2101,
0x20FA,0x20F4,0x20EE,0x20E7,0x20E1,0x20DB,0x20D4,0x20CE,
0x20C8,0x20C2,0x20BB,0x20B5,0x20AF,0x20A9,0x20A2,0x209C,
0x2096,0x2090,0x208A,0x2083,0x207D,0x2077,0x2071,0x206B,
0x2065,0x205E,0x2058,0x2052,0x204C,0x2046,0x2040,0x203A,
0x2034,0x202D,0x2027,0x2021,0x201B,0x2015,0x200F,0x2009,
0x2003,0x1FFD,0x1FF7,0x1FF1,0x1FEB,0x1FE5,0x1FDF,0x1FD9,
0x1FD3,0x1FCD,0x1FC7,0x1FC1,0x1FBB,0x1FB5,0x1FAF,0x1FA9,
0x1FA3,0x1F9D,0x1F97,0x1F91,0x1F8B,0x1F85,0x1F7F,0x1F79,
0x1F73,0x1F6D,0x1F68,0x1F62,0x1F5C,0x1F56,0x1F50,0x1F4A,
0x1F44,0x1F3E,0x1F39,0x1F33,0x1F2D,0x1F27,0x1F21,0x1F1B,
0x1F16,0x1F10,0x1F0A,0x1F04,0x1EFE,0x1EF9,0x1EF3,0x1EED
};*/

int a76489_lookup[4][0x100] =
{{
  /*0*/
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
},{
  /*1*/
  0x0000,0x1F97,0x1FEB,0x2040,0x209C,0x20EE,0x2140,0x2194,
  0x21EF,0x223F,0x228F,0x22E1,0x2349,0x239D,0x23F2,0x2449,
  0x249A,0x24EC,0x253F,0x2593,0x25F0,0x263F,0x268F,0x26E0,
  0x274B,0x279E,0x27F3,0x2849,0x28A0,0x28F0,0x2941,0x2993,
  0x29EF,0x2A43,0x2A99,0x2AF0,0x2B48,0x2B97,0x2BE8,0x2C39,
  0x2CA1,0x2CF5,0x2D4B,0x2DA2,0x2DEF,0x2E3D,0x2E8C,0x2EDC,
  0x2F44,0x2F97,0x2FEB,0x3040,0x30A2,0x30EE,0x3146,0x3194,
  0x31EF,0x323F,0x328F,0x32E1,0x3350,0x33A4,0x33FA,0x3451,
  0x349A,0x34F3,0x353F,0x359B,0x35F8,0x3647,0x3697,0x36E8,
  0x374B,0x379E,0x37F3,0x3849,0x38A0,0x38F9,0x3941,0x399C,
  0x39F8,0x3A43,0x3AA2,0x3AF0,0x3B52,0x3BA1,0x3BF2,0x3C44,
  0x3CAC,0x3D00,0x3D56,0x3DAD,0x3DEF,0x3E48,0x3E8C,0x3EE7,
  0x3F44,0x3FA3,0x3FEB,0x404C,0x40AF,0x40FA,0x4146,0x4194,
  0x41FC,0x424C,0x429D,0x42EF,0x435E,0x43B2,0x4408,0x445F,
  0x449A,0x44F3,0x454E,0x45AA,0x4608,0x4647,0x46A7,0x46E8,
  0x474B,0x47AF,0x47F3,0x485A,0x48A0,0x490B,0x4953,0x499C,
  0x4A0B,0x4A56,0x4AA2,0x4AF0,0x4B65,0x4BB5,0x4C06,0x4C58,
  0x4CAC,0x4D00,0x4D56,0x4DAD,0x4E05,0x4E5E,0x4E8C,0x4EE7,
  0x4F44,0x4FA3,0x5003,0x5065,0x50C8,0x50FA,0x5160,0x5194,
  0x51FC,0x5267,0x529D,0x530A,0x537A,0x53B2,0x5425,0x545F,
  0x549A,0x5511,0x554E,0x55C9,0x5608,0x5647,0x56C7,0x5709,
  0x574B,0x57D1,0x5815,0x585A,0x58A0,0x592F,0x5977,0x59C1,
  0x5A0B,0x5A56,0x5AA2,0x5AF0,0x5B8D,0x5BDE,0x5C2F,0x5C82,
  0x5CD6,0x5D2B,0x5D81,0x5DD9,0x5E31,0x5E8C,0x5E8C,0x5EE7,
  0x5F44,0x5FA3,0x6003,0x6065,0x60C8,0x612D,0x6194,0x6194,
  0x61FC,0x6267,0x62D3,0x6342,0x63B2,0x63B2,0x6425,0x649A,
  0x649A,0x6511,0x658B,0x6608,0x6608,0x6687,0x6709,0x6709,
  0x678D,0x6815,0x6815,0x68A0,0x68A0,0x692F,0x69C1,0x69C1,
  0x6A56,0x6A56,0x6AF0,0x6AF0,0x6B8D,0x6C2F,0x6C2F,0x6CD6,
  0x6CD6,0x6D81,0x6D81,0x6E31,0x6E31,0x6EE7,0x6EE7,0x6EE7,
  0x6FA3,0x6FA3,0x7065,0x7065,0x712D,0x712D,0x71FC,0x71FC,
  0x71FC,0x72D3,0x72D3,0x73B2,0x73B2,0x73B2,0x749A,0x749A
},{
  /*2*/
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x2396,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x28E7,0x0000,0x0000,
  0x0000,0x2A3A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x2CEB,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x2F8B,0x0000,0x0000,0x0000,0x30E1,0x0000,0x0000,
  0x0000,0x3231,0x0000,0x0000,0x0000,0x3396,0x0000,0x0000,
  0x0000,0x34E4,0x0000,0x0000,0x0000,0x3637,0x0000,0x0000,
  0x0000,0x378D,0x0000,0x0000,0x0000,0x38E7,0x0000,0x0000,
  0x0000,0x3A30,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x3CEB,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x3F8B,0x0000,0x0000,0x0000,0x40E1,0x0000,0x0000,
  0x0000,0x4231,0x0000,0x0000,0x0000,0x4396,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x4627,0x0000,0x0000,
  0x0000,0x478D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x4A30,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x4CD6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x50C8,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x537A,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x6194,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
},{
  /*3*/
  0x1F39,0x1F8B,0x1FDF,0x2034,0x2090,0x20E1,0x2133,0x2187,
  0x21E2,0x2231,0x2282,0x22D3,0x233B,0x238F,0x23E4,0x243B,
  0x248B,0x24DD,0x2530,0x2584,0x25E0,0x262F,0x267F,0x26CF,
  0x273A,0x278D,0x27E2,0x2838,0x288F,0x28DE,0x292F,0x2980,
  0x29DC,0x2A30,0x2A86,0x2ADC,0x2B34,0x2B83,0x2BD4,0x2C25,
  0x2C8C,0x2CE0,0x2D35,0x2D8C,0x2DD9,0x2E26,0x2E75,0x2EC5,
  0x2F2D,0x2F7F,0x2FD3,0x3027,0x308A,0x30D4,0x312D,0x317A,
  0x31D5,0x3224,0x3274,0x32C6,0x3334,0x3388,0x33DD,0x3433,
  0x347C,0x34D5,0x3520,0x357C,0x35D9,0x3627,0x3677,0x36C7,
  0x3729,0x377D,0x37D1,0x3826,0x387D,0x38D5,0x391D,0x3977,
  0x39D3,0x3A1E,0x3A7C,0x3AC9,0x3B2A,0x3B79,0x3BC9,0x3C1B,
  0x3C82,0x3CD6,0x3D2B,0x3D81,0x3DC2,0x3E1B,0x3E5E,0x3EB9,
  0x3F16,0x3F73,0x3FBB,0x401B,0x407D,0x40C8,0x4113,0x4160,
  0x41C8,0x4217,0x4267,0x42B8,0x4326,0x437A,0x43CF,0x4425,
  0x445F,0x44B8,0x4511,0x456D,0x45C9,0x4608,0x4667,0x46A7,
  0x4709,0x476C,0x47AF,0x4815,0x485A,0x48C4,0x490B,0x4953,
  0x49C1,0x4A0B,0x4A56,0x4AA2,0x4B17,0x4B65,0x4BB5,0x4C06,
  0x4C58,0x4CAC,0x4D00,0x4D56,0x4DAD,0x4E05,0x4E31,0x4E8C,
  0x4EE7,0x4F44,0x4FA3,0x5003,0x5065,0x5096,0x50FA,0x512D,
  0x5194,0x51FC,0x5231,0x529D,0x530A,0x5342,0x53B2,0x53EB,
  0x5425,0x549A,0x54D5,0x554E,0x558B,0x55C9,0x5647,0x5687,
  0x56C7,0x574B,0x578D,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
}};

/*colour lookup table for modes 0, 3, 4 and 6*/
int video_colourlookup1[0x10] = {0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1};
/*colour lookup table for modes 1 and 5*/
int video_colourlookup2[0x10] = {0,0,1,1,0,0,1,1,2,2,3,3,2,2,3,3};
char videoula_physical0[0x10] = {0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7};
char videoula_physical1[0x10] = {0,1,2,3,4,5,6,7,7,6,5,4,3,2,1,0};
char videoula_palette0[0x10] = {0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7};
char videoula_palette1[0x10] = {0,1,2,3,4,5,6,7,7,6,5,4,3,2,1,0};
char videoula_palette[0x10];

_kernel_swi_regs regs;
/*jmp_buf jmpbuffer;*/
clock_t timer, video_timer;

char memory[0x10000];
char r6502_a;
char r6502_x;
char r6502_y;
char r6502_sp;
char r6502_ps;

int address;
char value1, value2;
char nlo, nhi;

char buffer1[12];
char buffer2[12];

/*int channeltime[4];*/

int loc_video_addr; /*screen address of local system*/
int bbc_video_mode; /*bbc video_mode*/
int bbc_video_addr; /*bbc video address*/
int videoula_palettevalue;
int videoula_flashcolour;

char *cscreen;

int quit, escape;

int getword(char *block)
{
  int nreturn;
  nreturn = block[0];
  nreturn |= (block[1] << 8);
  nreturn |= (block[2] << 16);
  nreturn |= (block[3] << 24);
  return (nreturn);
}

void setword(char *block,int value)
{
  block[0] = (value & 0xFF);
  block[1] = (value & 0xFF00) >> 8;
  block[2] = (value & 0xFF0000) >> 16;
  block[3] = (value & 0xFF000000) >> 24;
}

void sound(void)
{
  int address,channel,amplitude,pitch,duration;
  address = (r6502_y << 8) | r6502_x;
  channel = (memory[address] & 0x0F);
  amplitude = (memory[address+3] << 8) | memory[address+2];
  if (amplitude > 0)
    amplitude = -15;
  else if (amplitude != 0)
    amplitude |= 0xFFFF0000; /*-= 0x10000;*/
  pitch = (memory[address+5] << 8) | memory[address+4];
  duration = (memory[address+7] << 8) | memory[address+6];
  if (channel == 0)
  {
    if (amplitude == 0)
    {
      regs.r[0] = 1;
      regs.r[1] = 0;
      regs.r[2] = 0;
      regs.r[3] = 1;
      _kernel_swi(Sound_Control,&regs,&regs);
    }
    else
    {
      regs.r[0] = 1;
      regs.r[1] = amplitude;
      regs.r[2] = 0x8000+pitch;
      regs.r[3] = duration;
      _kernel_swi(Sound_Control,&regs,&regs);
    }
  }
  else
  {
    if (amplitude == 0)
    {
      regs.r[0] = (channel+1);
      regs.r[1] = 0;
      regs.r[2] = a76489_lookup[channel][pitch];
      regs.r[3] = 1;
      _kernel_swi(Sound_Control,&regs,&regs);
    }
    else
    {
      regs.r[0] = (channel+1);
      regs.r[1] = amplitude;
      regs.r[2] = a76489_lookup[channel][pitch];
      regs.r[3] = duration;
      _kernel_swi(Sound_Control,&regs,&regs);
    }
  }
  /*if (duration == 0xFF)
    channeltime[channel] = 0;
  else
  {
    if (channeltime[channel] > 0)
    {
      while (clock() < channeltime[channel])
      {
      }
    }
    channeltime[channel] = clock() + (duration << 1);
  }*/
}

void osword(void)
{
  int address;
  switch (r6502_a)
  {
    case 0x00:
      /*read line from currently selected input into memory*/
      address = ((r6502_y << 8) | r6502_x);
      regs.r[0] = (int)(memory+((memory[address+1] << 8) | memory[address]));
      regs.r[1] = memory[address+2];
      regs.r[2] = memory[address+3];
      regs.r[3] = memory[address+4];
      _kernel_swi(OS_ReadLine,&regs,&regs);
      r6502_y = (regs.r[1] & 0xFF)+1;
      break;
    case 0x03:
      /*read interval timer*/
      regs.r[0] = 0x03;
      regs.r[1] = (int)(memory+((r6502_y << 8) | r6502_x));
      _kernel_swi(OS_Word,&regs,&regs);
      break;
    case 0x04:
      /*write interval timer*/
      regs.r[0] = 0x04;
      regs.r[1] = (int)(memory+((r6502_y << 8) | r6502_x));
      _kernel_swi(OS_Word,&regs,&regs);
      break;
    case 0x07:
      /*SOUND command*/
      sound();
      break;
    default:
      regs.r[0] = r6502_a;
      regs.r[1] = r6502_x;
      regs.r[2] = r6502_y;
      _kernel_swi(OS_Word,&regs,&regs);
      r6502_x = (regs.r[1] & 0xFF);
      r6502_y = (regs.r[2] & 0xFF);
      break;
  }
}

void r6502adc(int n)
{
  int nval;
  int nlob, nhib;

  if (!(r6502_ps & DFLAG))
  {
    nval = r6502_a+n;
    if (r6502_ps & CFLAG)
      nval++;
    if (nval >= 0x100)
      SETFLAG(CFLAG)
    else
      CLEARFLAG(CFLAG)
    if (!((r6502_a ^ n) & 0x80) AND ((r6502_a ^ nval) & 0x80))
      SETFLAG(VFLAG)
    else
      CLEARFLAG(VFLAG)
    nval &= 0xFF;
    r6502_a = nval;
    SETNFLAG(r6502_a)
    SETZFLAG(r6502_a)
  }
  else
  {
    nval = r6502_a+n;
    if (r6502_ps & CFLAG)
      nval++;
    SETZFLAG(nval)
    nlob = (r6502_a & 0x0F)+(n & 0x0F);
    if (r6502_ps & CFLAG)
      nlob++;
    if (nlob > 9)
      nlob += 6;
    nhib = (r6502_a >> 4)+(n >> 4);
    if (nlob > 0x0F)
      nhib++;
    nval = (nhib << 4) + (nlob & 0x0F);
    SETNFLAG(nval)
    if ((((nhib << 4) ^ r6502_a) & 0x80) AND !((r6502_a ^ n) & 0x80))
      SETFLAG(VFLAG)
    else
      CLEARFLAG(VFLAG)
    if (nhib > 9)
      nhib +=6;
    if (nhib > 0x0F)
      SETFLAG(CFLAG)
    else
      CLEARFLAG(CFLAG)
    r6502_a = (nhib << 4) + (nlob & 0x0F);
  }
}

void r6502jsr(int r6502_pc) /*,int address)*/
{
  r6502_pc--;
  STACK_PUSH((r6502_pc & 0xFF00)>>8);
  STACK_PUSH(r6502_pc & 0x00FF);
  /*r6502_pc = n;*/
  /*goto address;*/
  /*setjmp(jmpbuffer);*/
}

/*void r6502rts(void)
{
  int r6502_pc;
  STACK_POP(nlo);
  STACK_POP(nhi);
  r6502_pc = (nhi<<8)+nlo;
  r6502_pc++;*/
 /* longjump(jmpbuffer,value);*/
/*}*/

void r6502sbc(int n)
{
  int nval;
  int nlob, nhib;
  if (!(r6502_ps & DFLAG))
  {
    nval = r6502_a-n;
    if (!(r6502_ps & CFLAG))
      nval--;
    if (nval >= 0)
      SETFLAG(CFLAG)
    else
      CLEARFLAG(CFLAG)
    if (((r6502_a ^ nval) & 0x80) AND ((r6502_a ^ n) & 0x80))
      SETFLAG(VFLAG)
    else
      CLEARFLAG(VFLAG)
    nval &= 0xFF;
    SETNFLAG(nval)
    SETZFLAG(nval)
    r6502_a = nval;
  }
  else
  {
    nval = r6502_a-n;
    if (!(r6502_ps & CFLAG))
      nval--;
    nlob = (r6502_a & 0x0F)-(n & 0x0F);
    if (!(r6502_ps & CFLAG))
      nlob--;
    nhib = (r6502_a >> 4)-(n >> 4);
    if (nlob & 0x10)
    {
      nlob -= 6;
      nlob &= 0x0F;
      nhib--;
    }
    if (nhib & 0x10)
      nhib -= 6;
    if (nval >= 0)
      SETFLAG(CFLAG)
    else
      CLEARFLAG(CFLAG)
    if (((r6502_a ^ nval) & 0x80) AND ((r6502_a ^ n) & 0x80))
      SETFLAG(VFLAG)
    else
      CLEARFLAG(VFLAG)
    nval &= 0xFF;
    SETNFLAG(nval)
    SETZFLAG(nval)
    r6502_a = (nhib << 4) + (nlob & 0x0F);
  }
}

/*char readmode2(int address)
{*/
  /*screen address calulation routine by Michael Foot <mikef@voyager.co.nz>*/
  /*this is slow*/
  /*int nx,ny;
  char pixel1,pixel2;

  address -= 0x3000;
  if (address >= 0x5000)
    address &= 0x4FFF;
  nx = (address & 0xFFF8);
  nx = ((nx % 0x280) >> 2);

  ny = ((address / 0x280) << 3);
  ny += (address & 7);*/

  /*ny * 160*/
  /*address = (loc_video_addr + (ny << 7) + (ny << 5) + nx);
  cscreen = (char *)address;
  pixel1 = (cscreen[0] & 0x0F);
  pixel2 = (cscreen[1] & 0x0F);*/

  /*&08 &04 &02 &01*/
  /*pixel1 = ((pixel1 & 0x08)<<4) | ((pixel1 & 0x04)<<3) | ((pixel1 & 0x02)<<2) | ((pixel1 & 0x01)<<1);*/

  /*&08 &04 &02 &01*/
  /*pixel2 = ((pixel2 & 0x08)<<3) | ((pixel2 & 0x04)<<2) | ((pixel2 & 0x02)<<1) | (pixel2 & 0x01);

  return (pixel1 | pixel2);
}*/

char readmode2(int address)
{
  /*screen address calulation routine by Thomas Harte <t.harte@excite.com>*/
  /*this is fast*/
  int nx,ny,nyo;
  char pixel1,pixel2;
  address -= 0x3000;
  if (address >= 0x5000)
    address &= 0x4FFF;

  nyo = (address & 7);

  /*take away bottom 3 bits*/
  address >>= 3;

  /*in order to divide by 80, divide by 16 first, since 5*16=80*/
  ny = (address >> 4);

  /*now divide by 5 using a numeric method based on the observation that
    x/5 = x/4 - x/10, and hence x/10 = x/8 - x/20, etc.
    a few fractional bits are used to maintain some accuracy - either 3
    or 5 depending on the low bit, since this produces the right result*/
  if (ny & 1)
  {
    ny = + (ny << 1) - (ny >> 1)
       + (ny >> 3) - (ny >> 5)
       + (ny >> 7);
    ny &= ~7;
  }
  else
  {
    ny = + (ny << 3) - (ny << 1)
       + (ny >> 1) - (ny >> 3)
       + (ny >> 5) - (ny >> 7);
    ny = (ny >> 2) & ~7;
  }

  /*get x just with address - (y*60) = offset - y*64 - y*16*/
  nx = address - (ny << 3) - (ny << 1);

  /*add back low 3 bits*/
  ny += nyo;

  /*ny * 160*/
  address = (loc_video_addr + (ny << 7) + (ny << 5) + (nx<<1));
  cscreen = (char *)address;
  pixel1 = (cscreen[0] & 0x0F);
  pixel2 = (cscreen[1] & 0x0F);

  /*&08 &04 &02 &01*/
  pixel1 = ((pixel1 & 0x08)<<4) | ((pixel1 & 0x04)<<3) | ((pixel1 & 0x02)<<2) | ((pixel1 & 0x01)<<1);

  /*&08 &04 &02 &01*/
  pixel2 = ((pixel2 & 0x08)<<3) | ((pixel2 & 0x04)<<2) | ((pixel2 & 0x02)<<1) | (pixel2 & 0x01);

  return (pixel1 | pixel2);
}

char readmode5(int address)
{
  /*screen address calulation routine by Thomas Harte <t.harte@excite.com>*/
  /*this is fast*/
  int nx,ny,nyo;
  char pixel1;

  address -= 0x5800;
  if (address >= 0x2800)
    address &= 0x27FF;

  nyo = (address & 7);

  /*take away bottom 3 bits*/
  address >>= 3;

  /*in order to divide by 40, divide by 8 first, since 5*8=40*/
  ny = (address >> 3);

  /*now divide by 5 using a numeric method based on the observation that
    x/5 = x/4 - x/10, and hence x/10 = x/8 - x/20, etc.
    a few fractional bits are used to maintain some accuracy - either 3
    or 5 depending on the low bit, since this produces the right result*/
  if (ny & 1)
  {
    ny = + (ny << 1) - (ny >> 1)
       + (ny >> 3) - (ny >> 5)
       + (ny >> 7);
    ny &= ~7;
  }
  else
  {
    ny = + (ny << 3) - (ny << 1)
       + (ny >> 1) - (ny >> 3)
       + (ny >> 5) - (ny >> 7);
    ny = (ny >> 2) & ~7;
  }

  /*get x just with address - (y*40) = offset - y*32 - y*/
  nx = address - (ny << 2) - ny;

  /*add back low 3 bits*/
  ny += nyo;

  /*ny * 80*/
  address = (loc_video_addr + (ny << 6) + (ny << 4) + (nx << 1));
  cscreen = (char *)address;

  pixel1  = ((cscreen[0] & 0x02) << 6) | ((cscreen[0] & 0x01) << 3);
  pixel1 |= ((cscreen[0] & 0x20) << 1) | ((cscreen[0] & 0x10) >> 2);
  pixel1 |= ((cscreen[1] & 0x02) << 4) | ((cscreen[1] & 0x01) << 1);
  pixel1 |= ((cscreen[1] & 0x20) >> 1) | ((cscreen[1] & 0x10) >> 4);

  return (pixel1);
}

char r6502read(int address)
{
  char result;

  if (address | 0x10000)
    address &= 0xFFFF;
  switch (address & 0xF000)
  {
    case 0x0000:
    case 0x1000:
    case 0x2000:
      /*RAM*/
      result = memory[address];
      break;
    case 0x3000:
    case 0x4000:
    case 0x5000:
    case 0x6000:
    case 0x7000:
      /*RAM*/
      if (address >= bbc_video_addr)
      {
        switch (bbc_video_mode)
        {
          case 0x02:
            result = readmode2(address);
            break;
          case 0x05:
            result = readmode5(address);
            break;
          /*case 0x07:
            readmode7(address);
            break;*/
          default:
            result = memory[address];
            break;
        }
      }
      else
        result = memory[address];
      break;
    case 0x8000:
    case 0x9000:
    case 0xA000:
    case 0xB000:
      /*ROM*/
      result = memory[address];
      break;
    case 0xC000:
    case 0xD000:
    case 0xE000:
      /*ROM*/
      result = memory[address];
      break;
    case 0xF000:
      result = memory[address];
      break;
    default:
      result = 0;
      break;
  }
  return (result);
}

/*void writemode2(int address, char value)
{*/
  /*screen address calulation routine by Michael Foot <mikef@voyager.co.nz>*/
  /*this is slow*/
  /*int nx,ny;
  char pixel1,pixel2;
  address -= 0x3000;
  if (address >= 0x5000)
    address &= 0x4FFF;
  nx = (address & 0xFFF8);
  nx = ((nx % 0x280) >> 2);

  ny = ((address / 0x280) << 3);
  ny += (address & 7);*/

  /*&08 &04 &02 &01*/
  /*pixel1 = ((value & 0x80)>>4) | ((value & 0x20)>>3) | ((value & 0x08)>>2) | ((value & 0x02)>>1);*/

  /*&08 &04 &02 &01*/
  /*pixel2 = ((value & 0x40)>>3) | ((value & 0x10)>>2) | ((value & 0x04)>>1) | (value & 0x01);*/

  /*ny * 160*/
  /*address = (loc_video_addr + (ny << 7) + (ny << 5) + nx);
  cscreen = (char *)address;
  cscreen[0] = ((pixel1 << 4) | pixel1);
  cscreen[1] = ((pixel2 << 4) | pixel2);*/
/*}*/

void writemode2(int address, char value)
{
  /*screen address calulation routine by Thomas Harte <t.harte@excite.com>*/
  /*this is fast*/
  int nx,ny,nyo;
  char pixel1,pixel2;

  address -= 0x3000;
  if (address >= 0x5000)
    address &= 0x4FFF;

  nyo = (address & 7);

  /*take away bottom 3 bits*/
  address >>= 3;

  /*in order to divide by 80, divide by 16 first, since 5*16=80*/
  ny = (address >> 4);

  /*now divide by 5 using a numeric method based on the observation that
    x/5 = x/4 - x/10, and hence x/10 = x/8 - x/20, etc.
    a few fractional bits are used to maintain some accuracy - either 3
    or 5 depending on the low bit, since this produces the right result*/
  if (ny & 1)
  {
    ny = + (ny << 1) - (ny >> 1)
       + (ny >> 3) - (ny >> 5)
       + (ny >> 7);
    ny &= ~7;
  }
  else
  {
    ny = + (ny << 3) - (ny << 1)
       + (ny >> 1) - (ny >> 3)
       + (ny >> 5) - (ny >> 7);
    ny = (ny >> 2) & ~7;
  }

  /*get x just with address - (y*60) = offset - y*64 - y*16*/
  nx = address - (ny << 3) - (ny << 1);

  /*add back low 3 bits*/
  ny += nyo;

  /*&08 &04 &02 &01*/
  pixel1 = ((value & 0x80)>>4) | ((value & 0x20)>>3) | ((value & 0x08)>>2) | ((value & 0x02)>>1);

  /*&08 &04 &02 &01*/
  pixel2 = ((value & 0x40)>>3) | ((value & 0x10)>>2) | ((value & 0x04)>>1) | (value & 0x01);

  /*ny * 160*/
  address = (loc_video_addr + (ny << 7) + (ny << 5) + (nx<<1));
  cscreen = (char *)address;

  pixel1 = videoula_palette[pixel1];
  cscreen[0] = ((pixel1 << 4) | pixel1);
  pixel2 = videoula_palette[pixel2];
  cscreen[1] = ((pixel2 << 4) | pixel2);
}

void writemode5(int address, char value)
{
  /*screen address calulation routine by Thomas Harte <t.harte@excite.com>*/
  /*this is fast*/
  int nx,ny,nyo;
  char pixel1,pixel2,pixel3,pixel4;

  address -= 0x5800;
  if (address >= 0x2800)
    address &= 0x27FF;

  nyo = (address & 7);

  /*take away bottom 3 bits*/
  address >>= 3;

  /*in order to divide by 40, divide by 8 first, since 5*8=40*/
  ny = (address >> 3);

  /*now divide by 5 using a numeric method based on the observation that
    x/5 = x/4 - x/10, and hence x/10 = x/8 - x/20, etc.
    a few fractional bits are used to maintain some accuracy - either 3
    or 5 depending on the low bit, since this produces the right result*/
  if (ny & 1)
  {
    ny = + (ny << 1) - (ny >> 1)
       + (ny >> 3) - (ny >> 5)
       + (ny >> 7);
    ny &= ~7;
  }
  else
  {
    ny = + (ny << 3) - (ny << 1)
       + (ny >> 1) - (ny >> 3)
       + (ny >> 5) - (ny >> 7);
    ny = (ny >> 2) & ~7;
  }

  /*get x just with address - (y*40) = offset - y*32 - y*/
  nx = address - (ny << 2) - ny;

  /*add back low 3 bits*/
  ny += nyo;

  /*ny * 80*/
  address = (loc_video_addr + (ny << 6) + (ny << 4) + (nx << 1));
  cscreen = (char *)address;

  /*&02 &01*/
  pixel1 = ((value & 0x80)>>6) | ((value & 0x08)>>3);

  /*&08 &04*/
  pixel2 = ((value & 0x40)>>5) | ((value & 0x04)>>2);

  /*&20 &10*/
  pixel3 = ((value & 0x20)>>4) | ((value & 0x02)>>1);

  /*&80 &40*/
  pixel4 = ((value & 0x10)>>3) | (value & 0x01);

  cscreen[0] = (pixel2 << 6) | (pixel2 << 4) | (pixel1 << 2) | pixel1;
  cscreen[1] = (pixel4 << 6) | (pixel4 << 4) | (pixel3 << 2) | pixel3;
}

void writemode7(int address, char value)
{
  char nx,ny;
  address -= 0x7C00;
  if (address >= 0x3E8)
    address -= 0x3E8;
  ny = (address / 40);
  nx = (address % 40);
  bbcvdu(31);
  bbcvdu(nx);
  bbcvdu(ny);
  bbcvdu(value | 0x80);
}

void videoulawrite(int address, char value)
{
  char n1,n2;
  if (address & 0x01)
  {
    /*palette*/
    n1 = (value >> 4); /*logical colour*/
    n2 = ((value & 0x0F) ^ 7); /*physical colour*/
    videoula_palettevalue = value;
    switch (bbc_video_mode)
    {
      case 0x00:
      case 0x03:
      case 0x04:
      case 0x06:
        /*1bpp*/
        videoula_palette0[n1] = videoula_physical0[n2];
        videoula_palette1[n1] = videoula_physical1[n2];
        n2 = video_colourlookup1[n1];
        if (videoula_flashcolour == 0)
          videoula_palette[n2] = videoula_palette0[n1];
        else
          videoula_palette[n2] = videoula_palette1[n1];
        break;
      case 0x01:
      case 0x05:
        /*2bpp*/
        videoula_palette0[n1] = videoula_physical0[n2];
        videoula_palette1[n1] = videoula_physical1[n2];
        n2 = video_colourlookup2[n1];
        if (videoula_flashcolour == 0)
          videoula_palette[n2] = videoula_palette0[n1];
        else
          videoula_palette[n2] = videoula_palette1[n1];
        break;
      default:
        videoula_palette0[n1] = videoula_physical0[n2];
        videoula_palette1[n1] = videoula_physical1[n2];
        if (videoula_flashcolour == 0)
          videoula_palette[n1] = videoula_palette0[n1];
        else
          videoula_palette[n1] = videoula_palette1[n1];
        break;
    }
  }
  else
    videoula_flashcolour = (value & 0x01);
}

void sheilawrite(int address, char value)
{
  switch (address & 0x00F4)
  {
    case 0x20:
    case 0x24:
    case 0x28:
    case 0x2C:
      /*&FE20 - &FE2F (VIDEOULA)*/
      videoulawrite(address, value);
      break;
  }
}

void r6502write(int address, char value)
{
  if (address | 0x10000)
    address &= 0xFFFF;
  switch (address & 0xF000)
  {
    case 0x0000:
    case 0x1000:
    case 0x2000:
      /*RAM*/
      memory[address] = value;
      break;
    case 0x3000:
    case 0x4000:
    case 0x5000:
    case 0x6000:
    case 0x7000:
      /*RAM*/
      memory[address] = value;
      /*check screen write here!*/
      if (address >= bbc_video_addr)
      {
        switch (bbc_video_mode)
        {
          case 0x02:
            writemode2(address,value);
            break;
          case 0x05:
            writemode5(address,value);
            break;
          case 0x07:
            writemode7(address,value);
            break;
        }
      }
      break;
    case 0x8000:
    case 0x9000:
    case 0xA000:
    case 0xB000:
      /*ROM*/
      break;
    case 0xC000:
    case 0xD000:
    case 0xE000:
      /*ROM*/
      break;
    case 0xF000:
      switch (address & 0x0F00)
      {
        case 0x0E00:
          sheilawrite(address, value);
          break;
      }
      /*printf("F000 &%X,&%X\n",address,value);*/
      break;
  }
}
void getscreenaddress(void)
{
  setword(buffer1,148);
  setword(buffer1+4,-1);
  regs.r[0] = (int)buffer1;
  regs.r[1] = (int)buffer2;
  _kernel_swi(OS_ReadVduVariables,&regs,&regs);
  loc_video_addr = getword(buffer2);
}

void initialise(void)
{
  /*set up keyboard translation table*/
  memory[0xF02B] = 0x03;
  memory[0xF02C] = 0x8C;
  memory[0xF02D] = 0x40;
  memory[0xF02E] = 0xFE;
  memory[0xF02F] = 0xA0;
  memory[0xF030] = 0x7F;
  memory[0xF031] = 0x8C;
  memory[0xF032] = 0x43;
  memory[0xF033] = 0xFE;
  memory[0xF034] = 0x8E;
  memory[0xF035] = 0x4F;
  memory[0xF036] = 0xFE;
  memory[0xF037] = 0xAE;
  memory[0xF038] = 0x4F;
  memory[0xF039] = 0xFE;
  memory[0xF03A] = 0x60;
  memory[0xF03B] = 0x71;
  memory[0xF03C] = 0x33;
  memory[0xF03D] = 0x34;
  memory[0xF03E] = 0x35;
  memory[0xF03F] = 0x84;
  memory[0xF040] = 0x38;
  memory[0xF041] = 0x87;
  memory[0xF042] = 0x2D;
  memory[0xF043] = 0x5E;
  memory[0xF044] = 0x8C;
  memory[0xF045] = 0x84;
  memory[0xF046] = 0xEC;
  memory[0xF047] = 0x86;
  memory[0xF048] = 0xED;
  memory[0xF049] = 0x60;
  memory[0xF04A] = 0x00;
  memory[0xF04B] = 0x80;
  memory[0xF04C] = 0x77;
  memory[0xF04D] = 0x65;
  memory[0xF04E] = 0x74;
  memory[0xF04F] = 0x37;
  memory[0xF050] = 0x69;
  memory[0xF051] = 0x39;
  memory[0xF052] = 0x30;
  memory[0xF053] = 0x5F;
  memory[0xF054] = 0x8E;
  memory[0xF055] = 0x6C;
  memory[0xF056] = 0xFE;
  memory[0xF057] = 0xFD;
  memory[0xF058] = 0x6C;
  memory[0xF059] = 0xFA;
  memory[0xF05A] = 0x00;
  memory[0xF05B] = 0x31;
  memory[0xF05C] = 0x32;
  memory[0xF05D] = 0x64;
  memory[0xF05E] = 0x72;
  memory[0xF05F] = 0x36;
  memory[0xF060] = 0x75;
  memory[0xF061] = 0x6F;
  memory[0xF062] = 0x70;
  memory[0xF063] = 0x5B;
  memory[0xF064] = 0x8F;
  memory[0xF065] = 0x2C;
  memory[0xF066] = 0xB7;
  memory[0xF067] = 0xD9;
  memory[0xF068] = 0x6C;
  memory[0xF069] = 0x28;
  memory[0xF06A] = 0x02;
  memory[0xF06B] = 0x01;
  memory[0xF06C] = 0x61;
  memory[0xF06D] = 0x78;
  memory[0xF06E] = 0x66;
  memory[0xF06F] = 0x79;
  memory[0xF070] = 0x6A;
  memory[0xF071] = 0x6B;
  memory[0xF072] = 0x40;
  memory[0xF073] = 0x3A;
  memory[0xF074] = 0x0D;
  memory[0xF075] = 0x00;
  memory[0xF076] = 0xFF;
  memory[0xF077] = 0x01;
  memory[0xF078] = 0x02;
  memory[0xF079] = 0x09;
  memory[0xF07A] = 0x0A;
  memory[0xF07B] = 0x02;
  memory[0xF07C] = 0x73;
  memory[0xF07D] = 0x63;
  memory[0xF07E] = 0x67;
  memory[0xF07F] = 0x68;
  memory[0xF080] = 0x6E;
  memory[0xF081] = 0x6C;
  memory[0xF082] = 0x3B;
  memory[0xF083] = 0x5D;
  memory[0xF084] = 0x7F;
  memory[0xF085] = 0xAC;
  memory[0xF086] = 0x44;
  memory[0xF087] = 0x02;
  memory[0xF088] = 0xA2;
  memory[0xF089] = 0x00;
  memory[0xF08A] = 0x60;
  memory[0xF08B] = 0x00;
  memory[0xF08C] = 0x7A;
  memory[0xF08D] = 0x20;
  memory[0xF08E] = 0x76;
  memory[0xF08F] = 0x62;
  memory[0xF090] = 0x6D;
  memory[0xF091] = 0x2C;
  memory[0xF092] = 0x2E;
  memory[0xF093] = 0x2F;
  memory[0xF094] = 0x8B;
  memory[0xF095] = 0xAE;
  memory[0xF096] = 0x41;
  memory[0xF097] = 0x02;
  memory[0xF098] = 0x4C;
  memory[0xF099] = 0xAD;
  memory[0xF09A] = 0xE1;
  memory[0xF09B] = 0x1B;
  memory[0xF09C] = 0x81;
  memory[0xF09D] = 0x82;
  memory[0xF09E] = 0x83;
  memory[0xF09F] = 0x85;
  memory[0xF0A0] = 0x86;
  memory[0xF0A1] = 0x88;
  memory[0xF0A2] = 0x89;
  memory[0xF0A3] = 0x5C;
  memory[0xF0A4] = 0x8D;
  memory[0xF0A5] = 0x6C;
  memory[0xF0A6] = 0x20;
  memory[0xF0A7] = 0x02;
  memory[0xF0A8] = 0xD0;
  memory[0xF0A9] = 0xEB;
  memory[0xF0AA] = 0xA2;

  r6502_a = 0x00;
  r6502_x = 0x00;
  r6502_y = 0x00;
  r6502_ps = 0x00;
  r6502_sp = 0xFF;

  /*channeltime[0] = 0;
  channeltime[1] = 0;
  channeltime[2] = 0;
  channeltime[3] = 0;*/

  bbc_video_mode = 0x07;
  bbc_video_addr = 0x7C00;

  videoula_palettevalue = 0;
  videoula_flashcolour = 0;
  video_timer = clock() + TIME_50HZ;
  quit = FALSE;

  /*disable escape*/
  regs.r[0] = 0xDC;
  regs.r[1] = 0xFF;
  regs.r[2] = 0x00;
  _kernel_swi(OS_Byte,&regs,&regs);
  escape = regs.r[1];

  _kernel_oscli("BeebSoundInitialise");
}

void finalise(void)
{
  _kernel_oscli("BeebSoundCloseDown");

  /*RMKILL BEEBSOUND*/
  strcpy(memory,"BeebSound");
  regs.r[0] = 4;
  regs.r[1] = (int)memory;
  _kernel_swi(OS_Module,&regs,&regs);

  /*enable escape*/
  regs.r[0] = 0xDC;
  regs.r[1] = escape;
  regs.r[2] = 0x00;
  _kernel_swi(OS_Byte,&regs,&regs);

  /*clear screen*/
  bbcvdu(0x0C);
}
