diff --git a/presets/cpc/hello.asm b/presets/cpc/hello.asm new file mode 100644 index 00000000..156c0bed --- /dev/null +++ b/presets/cpc/hello.asm @@ -0,0 +1,31 @@ + +; from https://www.chibiakumas.com/z80/helloworld.php#LessonH1 + +PrintChar = 0xbb5a +WaitChar = 0xbb06 + + org 0x4000 + +Start: + ld hl,Message ;Address of string + call PrintString ;Show String to screen + call WaitChar + ret ;Finished Hello World + +PrintString: + ld a,(hl) ;Print a '255' terminated string + cp 255 + ret z + inc hl + call PrintChar + jr PrintString + +Message: + db 'Hello World! Press a key...',255 + +NewLine: + ld a,13 ;Carriage return + call PrintChar + ld a,10 ;Line Feed + call PrintChar + ret diff --git a/presets/cpc/keyboard_redefine.c b/presets/cpc/keyboard_redefine.c new file mode 100644 index 00000000..fd1f6682 --- /dev/null +++ b/presets/cpc/keyboard_redefine.c @@ -0,0 +1,63 @@ + +// from https://github.com/cpcitor/cpcrslib/tree/master/examples + +#include "cpcrslib.h" + +void wait(void){ + __asm + + _kkk: + ld b,#100 + llll: + halt + djnz llll + __endasm; +} + +main() +{ + cpc_SetModo(1); + + cpc_AssignKey(4,0x4804); // key "ESC" + + cpc_PrintStr("Welcome to cpcrslib keyboard utilities."); + cpc_PrintStr("Press a Key to redefine as #1"); + cpc_RedefineKey(0); //redefine key. There are 12 available keys (0..11) + cpc_PrintStr("Done!"); + + + cpc_PrintStr("Now, press any key to continue"); + while(!(cpc_AnyKeyPressed())){} + + cpc_PrintStr("Well done! Let's do it again"); + + cpc_PrintStr("Press any key to continue"); + while(!(cpc_AnyKeyPressed())){} + + + cpc_PrintStr("Press a Key to redefine as #3"); + cpc_RedefineKey(3); //redefine key. There are 12 available keys (0..11) + cpc_PrintStr("Done!"); + + + wait(); + cpc_SetModo(1); + + cpc_SetBorder(3); + + cpc_PrintStr("Now let's test the selected keys. Press ESC to EXIT"); + + cpc_PrintStr("Press a Key to test it.."); + while (!cpc_TestKey(4)) { // IF NOT ESC is pressed + + if (cpc_TestKey(0)) { //test if the key has been pressed. + cpc_PrintStr("OK Key #1"); + } + if (cpc_TestKey(3)) { //test if the key has been pressed. + cpc_PrintStr("OK Key #2"); + } + //else cpc_PrintStr(no); + } + return 0; + +} diff --git a/presets/cpc/sprite_demo.c b/presets/cpc/sprite_demo.c new file mode 100644 index 00000000..963a0e0d --- /dev/null +++ b/presets/cpc/sprite_demo.c @@ -0,0 +1,262 @@ + +// from https://github.com/cpcitor/cpcrslib/tree/master/examples + +#include "cpcrslib.h" + +extern unsigned char sp_1[]; //masked sprite data +extern unsigned char sp_2[]; //masked sprite data +extern unsigned char tintas[]; //inks +extern unsigned char buffer[]; //inks + +struct sprite // minimun sprite structure +{ + char *sp0; //2 bytes 01 + char *sp1; //2 bytes 23 + int coord0; //2 bytes 45 current superbuffer address + int coord1; //2 bytes 67 old superbuffer address + unsigned char cx, cy; //2 bytes 89 current coordinates + unsigned char ox, oy; //2 bytes 1011 old coordinates + unsigned char move1; // los bits 4,3,2 definen el tipo de dibujo!! + unsigned char move; // in this example, to know the movement direction of the sprite +}; + +struct sprite sprite00,sprite01,sprite02; + +void data(void) +{ + __asm +_buffer: + .db #30 +_sp_1: + .db #4,#15 //sprite dimensions in bytes withd, height + .db #0xFF,#0x00,#0x00,#0xCF,#0x00,#0xCF,#0xFF,#0x00 //data: mask, sprite, mask, sprite... + .db #0xAA,#0x45,#0x00,#0x3C,#0x00,#0x3C,#0x55,#0x8A + .db #0x00,#0x8A,#0x00,#0x55,#0x00,#0xAA,#0x00,#0x45 + .db #0x00,#0x8A,#0x00,#0x20,#0x00,#0x00,#0x00,#0x65 + .db #0x00,#0x28,#0x00,#0x55,#0x00,#0xAA,#0x00,#0x14 + .db #0x00,#0x7D,#0x00,#0xBE,#0x00,#0xFF,#0x00,#0xBE + .db #0xAA,#0x14,#0x00,#0xFF,#0x00,#0xBE,#0x55,#0x28 + .db #0xAA,#0x00,#0x00,#0x3C,#0x00,#0x79,#0x55,#0x00 + .db #0x00,#0x51,#0x00,#0x51,#0x00,#0xA2,#0x55,#0xA2 + .db #0x00,#0xF3,#0x00,#0x10,#0x00,#0x20,#0x00,#0xF3 + .db #0x00,#0xF3,#0x00,#0x51,#0x00,#0xA2,#0x00,#0xF3 + .db #0x55,#0x28,#0x00,#0x0F,#0x00,#0x0F,#0xAA,#0x14 + .db #0xFF,#0x00,#0x55,#0x0A,#0xAA,#0x05,#0xFF,#0x00 + .db #0x55,#0x02,#0x55,#0x28,#0xAA,#0x14,#0xAA,#0x01 + .db #0x00,#0x03,#0x55,#0x02,#0xAA,#0x01,#0x00,#0x03 + +_sp_2: + .db #4,#21 + .db #0xFF,#0x00,#0x00,#0xCC,#0x00,#0xCC,#0xFF,#0x00 + .db #0xFF,#0x00,#0xAA,#0x44,#0x55,#0x88,#0xFF,#0x00 + .db #0xFF,#0x00,#0xAA,#0x44,#0x55,#0x88,#0xFF,#0x00 + .db #0xFF,#0x00,#0xAA,#0x44,#0x55,#0x88,#0xFF,#0x00 + .db #0xFF,#0x00,#0x00,#0xCF,#0x00,#0xCF,#0xFF,#0x00 + .db #0xAA,#0x45,#0x00,#0xCF,#0x00,#0xCF,#0x55,#0x8A + .db #0xAA,#0x45,#0x00,#0xE5,#0x00,#0xDA,#0x55,#0x8A + .db #0xAA,#0x45,#0x00,#0xCF,#0x00,#0xCF,#0x55,#0x8A + .db #0xAA,#0x45,#0x00,#0xCF,#0x00,#0xCF,#0x55,#0x8A + .db #0xAA,#0x45,#0x00,#0xCF,#0x00,#0xCF,#0x55,#0x8A + .db #0xAA,#0x45,#0x00,#0xCF,#0x00,#0xCF,#0x55,#0x8A + .db #0xFF,#0x00,#0x00,#0xCF,#0x00,#0xCF,#0xFF,#0x00 + .db #0xAA,#0x01,#0x00,#0x03,#0x00,#0x03,#0x55,#0x02 + .db #0x00,#0xA9,#0x00,#0x03,#0x00,#0x03,#0x00,#0x56 + .db #0x00,#0xA9,#0x00,#0x03,#0x00,#0x03,#0x00,#0x56 + .db #0xAA,#0x01,#0x00,#0x03,#0x00,#0x03,#0x55,#0x02 + .db #0xAA,#0x01,#0x00,#0x03,#0x00,#0x03,#0x55,#0x02 + .db #0xAA,#0x01,#0x00,#0x06,#0x00,#0x09,#0x55,#0x02 + .db #0xFF,#0x00,#0x00,#0x0C,#0x00,#0x0C,#0xFF,#0x00 + .db #0xFF,#0x00,#0x00,#0x0C,#0x00,#0x0C,#0xFF,#0x00 + .db #0xFF,#0x00,#0x00,#0x0C,#0x00,#0x0C,#0xFF,#0x00 + +// There is a tool called Sprot that allows to generate masked sprites for z88dk. +// ask for it: www.amstrad.es/forum/ + +_tintas: //firmware inks + .db #0,#13,#1,#6,#26,#24,#15,#8,#10,#22,#14,#3,#18,#4,#11,#25 + __endasm; +} + + +void *p_sprites[7]; + +void initPointers() +{ + + p_sprites[0] = &sprite00; + p_sprites[1] = &sprite01; + p_sprites[2] = &sprite02; + +} + +void set_colours(void) +{ + unsigned char x; + for (x=0; x<16; x++) + { + cpc_SetInk(x,tintas[x]); + } + cpc_SetBorder(0); +} +void pause(void) +{ + __asm + ld b,#80 +pause_loop: + halt + djnz pause_loop + __endasm; +} +void collide(void) +{ + cpc_SetColour(16,1); + pause(); + cpc_SetColour(16,9); +} + +void draw_tilemap(void) +{ + unsigned char x,y; + //set the tiles of the map. In this example, the tile map is 32x16 tile + //Tile Map configuration file: TileMapConf.asm + + y=0; + for(x=0; x<32; x++) + { + cpc_SetTile(x,y,1); + } + for(y=1; y<15; y++) + { + for (x=0; x<32; x++) + { + cpc_SetTile(x,y,0); + } + } + y=15; + for (x=0; x<32; x++) + { + cpc_SetTile(x,y,2); + } +} + +void print_credits(void) +{ + cpc_PrintGphStrXY("SMALL;SPRITE;DEMO",9*2+3,20*8); + cpc_PrintGphStrXY("SDCC;;;CPCRSLIB",10*2+3,21*8); + cpc_PrintGphStrXY("BY;ARTABURU;2015",10*2+2,22*8); + cpc_PrintGphStrXY("ESPSOFT0) sprite00.cx--; + if (cpc_TestKey(2)==1 && sprite00.cy>0) sprite00.cy-=2; + if (cpc_TestKey(3)==1 && sprite00.cy<112) sprite00.cy+=2; + + // The other sprites are automatically moved + if (sprite01.move==0) //0 = left, 1 = right + { + if (sprite01.cx>0) sprite01.cx--; + else sprite01.move=1; + } + if (sprite01.move==1) //0 = left, 1 = right + { + if (sprite01.cx<60) sprite01.cx++; + else sprite01.move=0; + } + + if (sprite02.move==2) //2 = up, 3 = down + { + if (sprite02.cy>0) sprite02.cy-=2; + else sprite02.move=3; + } + if (sprite02.move==3) //2 = up, 3 = down + { + if (sprite02.cy<106) sprite02.cy+=2; + else sprite02.move=2; + } + + cpc_ResetTouchedTiles(); //clear touched tile table + + //Sprite phase 1 + cpc_PutSpTileMap(p_sprites[0]); //search the tiles where is and was the sprite + cpc_PutSpTileMap(p_sprites[1]); + cpc_PutSpTileMap(p_sprites[2]); + + cpc_UpdScr(); //Update the screen to new situatio (show the touched tiles) + + //Sprite phase 2 + cpc_PutMaskSpTileMap2b(p_sprites[0]); //Requires to move sprite with cpc_SpUpdX or cpc_SpUpdY + cpc_PutMaskSpTileMap2b(p_sprites[1]); + cpc_PutMaskSpTileMap2b(p_sprites[2]); + + cpc_ShowTileMap2(); //Show the touched tiles-> show the new sprite situatuion + + if (cpc_CollSp(p_sprites[0],p_sprites[1])) collide(); //test if there is collision between sprite00 and sprite01 + if (cpc_CollSp(p_sprites[0],p_sprites[2])) collide(); + + } +} diff --git a/res/cpc.bios b/res/cpc.bios new file mode 100644 index 00000000..048d6a76 Binary files /dev/null and b/res/cpc.bios differ diff --git a/res/cpc.wasm b/res/cpc.wasm new file mode 100755 index 00000000..d717ff96 Binary files /dev/null and b/res/cpc.wasm differ diff --git a/src/common/baseplatform.ts b/src/common/baseplatform.ts index 4d791a62..e7af32e6 100644 --- a/src/common/baseplatform.ts +++ b/src/common/baseplatform.ts @@ -791,7 +791,10 @@ export abstract class BaseMachinePlatform extends BaseDebugPl var videoFrequency; if (hasVideo(m)) { var vp = m.getVideoParams(); - this.video = new RasterVideo(this.mainElement, vp.width, vp.height, {overscan:!!vp.overscan,rotate:vp.rotate|0}); + this.video = new RasterVideo(this.mainElement, vp.width, vp.height, + {overscan: !!vp.overscan, + rotate: vp.rotate|0, + aspect: vp.aspect}); this.video.create(); m.connectVideo(this.video.getFrameData()); // TODO: support keyboard w/o video? diff --git a/src/common/devices.ts b/src/common/devices.ts index 93bd4593..4d8068ca 100644 --- a/src/common/devices.ts +++ b/src/common/devices.ts @@ -40,6 +40,7 @@ export interface VideoParams { overscan? : boolean; rotate? : number; videoFrequency? : number; // default = 60 + aspect? : number; } // TODO: frame buffer optimization (apple2, etc) diff --git a/src/common/emu.ts b/src/common/emu.ts index 5b5ebe86..0f439758 100644 --- a/src/common/emu.ts +++ b/src/common/emu.ts @@ -65,7 +65,7 @@ export function _setKeyboardEvents(canvas:HTMLElement, callback:KeyboardCallback }; }; -type VideoCanvasOptions = {rotate?:number, overscan?:boolean}; +type VideoCanvasOptions = {rotate?:number, overscan?:boolean, aspect?:number}; export class RasterVideo { @@ -113,6 +113,10 @@ export class RasterVideo { if (this.options && this.options.overscan) { this.vcanvas.css('padding','0px'); } + if (this.options && this.options.aspect) { + console.log(this.options); + this.vcanvas.css('aspect-ratio', this.options.aspect+""); + } this.ctx = canvas.getContext('2d'); this.imageData = this.ctx.createImageData(this.width, this.height); this.datau32 = new Uint32Array(this.imageData.data.buffer); diff --git a/src/common/wasmplatform.ts b/src/common/wasmplatform.ts index c7b1afb6..b7e93eeb 100644 --- a/src/common/wasmplatform.ts +++ b/src/common/wasmplatform.ts @@ -99,7 +99,7 @@ export abstract class BaseWASMMachine { } async loadWASM() { await this.fetchWASM(); - this.exports.memory.grow(64); // TODO: need more when probing? + this.exports.memory.grow(96); // TODO: need more when probing? await this.fetchBIOS(); await this.initWASM(); } diff --git a/src/machine/cpc.ts b/src/machine/cpc.ts new file mode 100644 index 00000000..a83a926c --- /dev/null +++ b/src/machine/cpc.ts @@ -0,0 +1,146 @@ + +//// WASM Machine + +import { KeyFlags } from "../common/emu"; +import { Machine } from "../common/baseplatform"; +import { TrapCondition } from "../common/devices"; +import { BaseWASMMachine } from "../common/wasmplatform"; + +const BIN_HEADER = [ + 0, + 0,0,0,0,0,0,0,0, + 0,0,0, + 0,0,0,0,0,0, + 1, + 0,0, + 0x0, 0x40, // load addr + 0, + 0x0, 0x0, // length + 0x0, 0x40, // start addr + 0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, +]; + +export class CPC_WASMMachine extends BaseWASMMachine implements Machine { + + numTotalScanlines = 312; + cpuCyclesPerLine = 224; + + joymask0 = 0; + + loadROM(rom: Uint8Array) { + let runaddr = 0x4000; //0x5de9; + let combined = new Uint8Array(rom.length + BIN_HEADER.length); + combined.set(BIN_HEADER, 0); + combined[24] = rom.length & 0xff; + combined[25] = rom.length >> 8; + combined[26] = runaddr & 0xff; + combined[27] = runaddr >> 8; + combined.set(rom, BIN_HEADER.length); + super.loadROM(combined); + } + reset() { + super.reset(); + // advance bios + this.exports.machine_exec(this.sys, 1000000); // TODO? + // load rom (SNA or BIN) + if (this.romptr && this.romlen) { + this.exports.machine_load_rom(this.sys, this.romptr, this.romlen); + } + } + advanceFrame(trap: TrapCondition) : number { + //var scanline = this.exports.machine_get_raster_line(this.sys); + var probing = this.probe != null; + if (probing) this.exports.machine_reset_probe_buffer(); + var clocks = super.advanceFrameClock(trap, Math.floor(1000000 / 50)); // TODO: use ticks, not msec + if (probing) this.copyProbeData(); + return clocks; + } + /* + z80_tick_t tick_cb; // 0 + uint64_t bc_de_hl_fa; // 8 + uint64_t bc_de_hl_fa_; // 16 + uint64_t wz_ix_iy_sp; // 24 + uint64_t im_ir_pc_bits; // 32 + uint64_t pins; // 48 + void* user_data; + z80_trap_t trap_cb; + void* trap_user_data; + int trap_id; + */ + getCPUState() { + this.exports.machine_save_cpu_state(this.sys, this.cpustateptr); + var s = this.cpustatearr; + var af = s[9] + (s[8]<<8); // not FA + var hl = s[10] + (s[11]<<8); + var de = s[12] + (s[13]<<8); + var bc = s[14] + (s[15]<<8); + var sp = s[24] + (s[25]<<8); + var iy = s[26] + (s[27]<<8); + var ix = s[28] + (s[29]<<8); + var pc = s[34] + (s[35]<<8); + var ir = s[36] + (s[37]<<8); + return { + PC:pc, + SP:sp, + AF:af, + BC:bc, + DE:de, + HL:hl, + IX:ix, + IY:iy, + IR:ir, + o:this.readConst(pc), + } + } + saveState() { + this.exports.machine_save_state(this.sys, this.stateptr); + return { + c:this.getCPUState(), + state:this.statearr.slice(0), + }; + } + loadState(state) : void { + this.statearr.set(state.state); + this.exports.machine_load_state(this.sys, this.stateptr); + } + getVideoParams() { + return {width:768, height:272, overscan:true, videoFrequency:50, aspect:1.3}; + } + setKeyInput(key: number, code: number, flags: number): void { + // TODO: handle shifted keys + if (key == 16 || key == 17 || key == 18 || key == 224) return; // meta keys + //console.log(key, code, flags); + //if (flags & KeyFlags.Shift) { key += 64; } + // convert to c64 (TODO: zx) + var mask = 0; + var mask2 = 0; + if (key == 37) { key = 0x8; mask = 0x4; } // LEFT + if (key == 38) { key = 0xb; mask = 0x1; } // UP + if (key == 39) { key = 0x9; mask = 0x8; } // RIGHT + if (key == 40) { key = 0xa; mask = 0x2; } // DOWN + if (key == 32) { mask = 0x10; } // FIRE + if (key == 65) { key = 65; mask2 = 0x4; } // LEFT + if (key == 87) { key = 87; mask2 = 0x1; } // UP + if (key == 68) { key = 68; mask2 = 0x8; } // RIGHT + if (key == 83) { key = 83; mask2 = 0x2; } // DOWN + if (key == 69) { mask2 = 0x10; } // FIRE + if (key == 113) { key = 0xf1; } // F2 + if (key == 115) { key = 0xf3; } // F4 + if (key == 119) { key = 0xf5; } // F8 + if (key == 121) { key = 0xf7; } // F10 + if (flags & KeyFlags.KeyDown) { + this.exports.machine_key_down(this.sys, key); + this.joymask0 |= mask; + } else if (flags & KeyFlags.KeyUp) { + this.exports.machine_key_up(this.sys, key); + this.joymask0 &= ~mask; + } + this.exports.cpc_joystick(this.sys, this.joymask0, 0); + } +} diff --git a/src/platform/_index.ts b/src/platform/_index.ts index 9669305f..3c7b32bb 100644 --- a/src/platform/_index.ts +++ b/src/platform/_index.ts @@ -10,6 +10,7 @@ export function importPlatform(name: string) : Promise { case "basic": return import("../platform/basic"); case "c64": return import("../platform/c64"); case "coleco": return import("../platform/coleco"); + case "cpc": return import("../platform/cpc"); case "devel": return import("../platform/devel"); case "galaxian": return import("../platform/galaxian"); case "kim1": return import("../platform/kim1"); diff --git a/src/platform/cpc.ts b/src/platform/cpc.ts new file mode 100644 index 00000000..3efff025 --- /dev/null +++ b/src/platform/cpc.ts @@ -0,0 +1,31 @@ + +import { CPC_WASMMachine } from "../machine/cpc"; +import { Platform, BaseZ80MachinePlatform } from "../common/baseplatform"; +import { PLATFORMS } from "../common/emu"; + +const CPC_PRESETS = [ + {id:'hello.asm', name:'Hello World (ASM)'}, + {id:'sprite_demo.c', name:'Sprite Demo (C)'}, + {id:'keyboard_redefine.c', name:'Keyboard Redefine (C)'}, +]; + +const CPC_MEMORY_MAP = { main:[ + {name:'BIOS', start:0x0000, size:0x4000, type:'rom'}, + {name:'Screen RAM', start:0xc000, size:0x4000, type:'ram'}, +] } + +// WASM CPC platform +class CPCWASMPlatform extends BaseZ80MachinePlatform implements Platform { + + newMachine() { return new CPC_WASMMachine('cpc'); } + + getPresets() { return CPC_PRESETS; } + getDefaultExtension() { return ".asm"; }; + readAddress(a) { return this.machine.readConst(a); } + getMemoryMap() { return CPC_MEMORY_MAP; } + showHelp() { + window.open("https://worldofspectrum.org/faq/reference/reference.htm", "_help"); + } +} + +PLATFORMS['cpc.464'] = CPCWASMPlatform; diff --git a/src/platform/vcs.ts b/src/platform/vcs.ts index f2fc2207..1a697807 100644 --- a/src/platform/vcs.ts +++ b/src/platform/vcs.ts @@ -486,7 +486,7 @@ class VCSStellaPlatform implements Platform { gamma: 0.8, scalingMode: this.Stellerator.ScalingMode.qis, tvEmulation: this.Stellerator.TvEmulation.composite, - phosphorLevel: 0.5, + phosphorLevel: 0.25, scanlineLevel: 0.2, keyboardTarget: this.mainElement } diff --git a/src/worker/lib/cpc/cpcrslib.h b/src/worker/lib/cpc/cpcrslib.h new file mode 100644 index 00000000..de4719ed --- /dev/null +++ b/src/worker/lib/cpc/cpcrslib.h @@ -0,0 +1,120 @@ + +#ifndef __cpcrslib_h__ +#define __cpcrslib_h__ + + +void cpc_SetMode( char color) __z88dk_fastcall; +void cpc_SetModo( char x) __z88dk_fastcall; +void cpc_SetColour(unsigned char num, char color) __z88dk_callee; +void cpc_SetInk(unsigned char num, unsigned char color) __z88dk_callee; +void cpc_SetBorder( char color) __z88dk_fastcall; +int cpc_GetScrAddress(char x, char y) __z88dk_callee; +void cpc_ClrScr(void); + + +void cpc_EnableFirmware(void); +void cpc_DisableFirmware(void); +unsigned char cpc_Random(void); +void cpc_PrintStr(char *text) __z88dk_fastcall; +void cpc_RRI(unsigned int pos, unsigned char w, unsigned char h) __z88dk_callee; +void cpc_RLI(unsigned int pos, unsigned char w, unsigned char h) __z88dk_callee; + + + + +void cpc_PutSprite(char *sprite, int posicion) __z88dk_callee; +void cpc_PutSp(char *sprite, char height, char width, int address) __z88dk_callee; +void cpc_PutSp4x14(char *sprite, int address) __z88dk_callee; +void cpc_PutSpriteXOR(char *sprite, int posicion) __z88dk_callee; +void cpc_PutSpXOR(char *sprite, char height, char width, int address) __z88dk_callee; +//void cpc_PutSpriteTr(char *sprite, int *posicion) __z88dk_callee; +void cpc_PutSpTr(char *sprite, char height, char width, int address) __z88dk_callee; +void cpc_GetSp(char *sprite, char alto, char ancho, int posicion) __z88dk_callee; +void cpc_PutMaskSprite(char *sprite,unsigned int addr) __z88dk_callee; +void cpc_PutMaskSp(char *sprite, char alto, char ancho, int posicion) __z88dk_callee; +void cpc_PutMaskSp4x16(char *sprite,unsigned int addr) __z88dk_callee; +void cpc_PutMaskSp2x8(char *sprite,unsigned int addr) __z88dk_callee; +unsigned char cpc_CollSp(char *sprite, char *sprite2) __z88dk_callee; + +void cpc_PutTile2x8(char *sprite, unsigned char x, unsigned char y); +void cpc_PutTile2x8b(char *sprite, int posicion) __z88dk_callee; + + +void cpc_PrintGphStr(char *text, int destino) __z88dk_callee; +void cpc_PrintGphStrM1(char *text, int destino) __z88dk_callee; +void cpc_PrintGphStr2X(char *text, int destino) __z88dk_callee; +void cpc_PrintGphStrM12X(char *text, int destino) __z88dk_callee; + +void cpc_PrintGphStrXY(char *text, char a, char b) __z88dk_callee; +void cpc_PrintGphStrXYM1(char *text, char a, char b) __z88dk_callee; +void cpc_PrintGphStrXY2X(char *text, char a, char b) __z88dk_callee; +void cpc_PrintGphStrXYM12X(char *text, char a, char b) __z88dk_callee; +void cpc_SetInkGphStr(char a, char b) __z88dk_callee; +void cpc_SetInkGphStrM1(char a, char b) __z88dk_callee; + + +void cpc_PrintGphStrStd(char color, char *cadena, int destino); +void cpc_PrintGphStrStdXY(char color, char *cadena, char x, char y); + + +int cpc_AnyKeyPressed(void); +void cpc_ScanKeyboard(void); +char cpc_TestKeyF(char number) __z88dk_fastcall; +void cpc_DeleteKeys(void); +void cpc_AssignKey(unsigned char tecla, int valor); +unsigned char cpc_TestKey(unsigned char tecla) __z88dk_fastcall; +void cpc_RedefineKey(unsigned char tecla) __z88dk_fastcall; + + +// Uncompression tools +void cpc_UnExo(char *origen, int destino) __z88dk_callee; +void cpc_Uncrunch(char *origen, int destino) __z88dk_callee; + + + + + + +// TILE MAP: +void cpc_InitTileMap(void); +void cpc_SetTile(unsigned char x, unsigned char y, unsigned char b); +void cpc_ShowTileMap(); +void cpc_ShowTileMap2(void); +void cpc_ResetTouchedTiles(void); + +void cpc_PutSpTileMap(char *sprite) __z88dk_fastcall; +void cpc_PutSpTileMapF(char *sprite); +void cpc_UpdScr(void); +void cpc_PutSpTileMap2b(char *sprite); +void cpc_PutMaskSpTileMap2b(char *sprite) __z88dk_fastcall; +void cpc_PutMaskInkSpTileMap2b(char *sprite); +void cpc_PutTrSpTileMap2b(char *sprite); +void cpc_PutTrSpriteTileMap2b(char *sprite); + +void cpc_SetTouchTileXY(unsigned char x, unsigned char y, unsigned char t); +unsigned char cpc_ReadTile(unsigned char x, unsigned char y) __z88dk_callee; + +//void cpc_SpUpdY(char *sprite, char valor); +//void cpc_SpUpdX(char *sprite, char valor); + +// Superbufer: +void cpc_SuperbufferAddress(char *sprite); +void cpc_ScrollRight00(void); +void cpc_ScrollRight01(void); +void cpc_ScrollLeft00(void); +void cpc_ScrollLeft01(void); + + +// Doble buffer: + +void cpc_SetSolidSprite(void); +void cpc_SetMaskedSprite(void); + +void cpc_ScrollRight(char z) __z88dk_fastcall; +void cpc_ScrollLeft(char z) __z88dk_fastcall; +void cpc_ScrollUp(char z) __z88dk_fastcall; +void cpc_ScrollDown(char z) __z88dk_fastcall; + + + +#endif /* __cpcrslib_h__ */ diff --git a/src/worker/lib/cpc/cpcrslib.lib b/src/worker/lib/cpc/cpcrslib.lib new file mode 100644 index 00000000..15f77afb Binary files /dev/null and b/src/worker/lib/cpc/cpcrslib.lib differ diff --git a/src/worker/lib/cpc/cpcrslib.lst b/src/worker/lib/cpc/cpcrslib.lst new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/src/worker/lib/cpc/cpcrslib.lst @@ -0,0 +1 @@ + diff --git a/src/worker/lib/cpc/crt0-cpc.lst b/src/worker/lib/cpc/crt0-cpc.lst new file mode 100644 index 00000000..211140d5 --- /dev/null +++ b/src/worker/lib/cpc/crt0-cpc.lst @@ -0,0 +1,75 @@ + ASxxxx Assembler V02.00 + NoICE + SDCC mods (Zilog Z80 / Hitachi HD64180), page 1. +Hexadecimal [16-Bits] + + + + 1 ; crt0.s for ZX Spectrum + 2 + 3 .module crt0 + 4 .globl _main + 5 .globl ___sdcc_call_hl + 6 + 7 ; Ordering of segments for the linker - copied from sdcc crt0.s + 8 .area _CODE + 9 .area _INITIALIZER + 10 .area _HOME + 11 .area _GSINIT + 12 .area _GSFINAL + 13 .area _DATA + 14 .area _INITIALIZED + 15 .area _BSEG + 16 .area _BSS + 17 .area _HEAP + 18 + 19 .area _CODE + 20 + 0000 21 _Start: + 0000 F3 [ 4] 22 di + 0001 ED 56 [ 8] 23 im 1 + 24 ; stack pointer already set by BIOS + 0003 CD 00 00 [17] 25 call gsinit ; Initialize global and static variables. + 0006 CD 00 00 [17] 26 call _main + 0009 C7 [11] 27 rst 0x0 ; Restart when main() returns. + 28 + 29 .area _GSINIT + 0000 30 gsinit:: + 31 + 32 ; Implicitly zeroed global and static variables. + 0000 01 00 00 [10] 33 ld bc, #l__DATA + 0003 78 [ 4] 34 ld a, b + 0004 B1 [ 4] 35 or a, c + 0005 28 0F [12] 36 jr Z, zeroed_data + 0007 21 00 00 [10] 37 ld hl, #s__DATA + 000A 36 00 [10] 38 ld (hl), #0x00 + 000C 0B [ 6] 39 dec bc + 000D 78 [ 4] 40 ld a, b + 000E B1 [ 4] 41 or a, c + 000F 28 05 [12] 42 jr Z, zeroed_data + 0011 5D [ 4] 43 ld e, l + 0012 54 [ 4] 44 ld d, h + 0013 13 [ 6] 45 inc de + 0014 ED B0 [21] 46 ldir + 0016 47 zeroed_data: + 48 + 49 ; Explicitly initialized global variables. + 0016 01 00 00 [10] 50 ld bc, #l__INITIALIZER + 0019 78 [ 4] 51 ld a, b + 001A B1 [ 4] 52 or a, c + 001B 28 08 [12] 53 jr Z, gsinit_static + 001D 11 00 00 [10] 54 ld de, #s__INITIALIZED + 0020 21 00 00 [10] 55 ld hl, #s__INITIALIZER + ASxxxx Assembler V02.00 + NoICE + SDCC mods (Zilog Z80 / Hitachi HD64180), page 2. +Hexadecimal [16-Bits] + + + + 0023 ED B0 [21] 56 ldir + 57 + 0025 58 gsinit_static: + 59 ; Explicitly initialized static variables inserted by compiler here. + 60 + 61 .area _GSFINAL + 0000 C9 [10] 62 ret + 63 + 64 .area _HOME + 65 diff --git a/src/worker/lib/cpc/crt0-cpc.rel b/src/worker/lib/cpc/crt0-cpc.rel new file mode 100644 index 00000000..bbedd953 --- /dev/null +++ b/src/worker/lib/cpc/crt0-cpc.rel @@ -0,0 +1,42 @@ +XL2 +H A areas 9 global symbols +M crt0 +S l__DATA Ref0000 +S _main Ref0000 +S s__DATA Ref0000 +S .__.ABS. Def0000 +S s__INITIALIZED Ref0000 +S ___sdcc_call_hl Ref0000 +S l__INITIALIZER Ref0000 +S s__INITIALIZER Ref0000 +A _CODE size A flags 0 addr 0 +A _INITIALIZER size 0 flags 0 addr 0 +A _HOME size 0 flags 0 addr 0 +A _GSINIT size 25 flags 0 addr 0 +S gsinit Def0000 +A _GSFINAL size 1 flags 0 addr 0 +A _DATA size 0 flags 0 addr 0 +A _INITIALIZED size 0 flags 0 addr 0 +A _BSEG size 0 flags 0 addr 0 +A _BSS size 0 flags 0 addr 0 +A _HEAP size 0 flags 0 addr 0 +T 00 00 +R 00 00 00 00 +T 00 00 F3 ED 56 CD 00 00 CD 00 00 C7 +R 00 00 00 00 00 06 03 00 02 09 01 00 +T 00 00 +R 00 00 03 00 +T 00 00 01 00 00 78 B1 28 0F 21 00 00 36 00 0B 78 +R 00 00 03 00 02 03 00 00 02 0A 02 00 +T 0E 00 B1 28 05 5D 54 13 ED B0 +R 00 00 03 00 +T 16 00 +R 00 00 03 00 +T 16 00 01 00 00 78 B1 28 08 11 00 00 21 00 00 ED +R 00 00 03 00 02 03 06 00 02 0A 04 00 02 0D 07 00 +T 24 00 B0 +R 00 00 03 00 +T 25 00 +R 00 00 03 00 +T 00 00 C9 +R 00 00 04 00 diff --git a/src/worker/lib/cpc/crt0-cpc.s b/src/worker/lib/cpc/crt0-cpc.s new file mode 100644 index 00000000..0e508867 --- /dev/null +++ b/src/worker/lib/cpc/crt0-cpc.s @@ -0,0 +1,65 @@ +; crt0.s for ZX Spectrum + + .module crt0 + .globl _main + .globl ___sdcc_call_hl + + ; Ordering of segments for the linker - copied from sdcc crt0.s + .area _CODE + .area _INITIALIZER + .area _HOME + .area _GSINIT + .area _GSFINAL + .area _DATA + .area _INITIALIZED + .area _BSEG + .area _BSS + .area _HEAP + + .area _CODE + +_Start: + di + im 1 + ; stack pointer already set by BIOS + call gsinit ; Initialize global and static variables. + call _main + rst 0x0 ; Restart when main() returns. + + .area _GSINIT +gsinit:: + + ; Implicitly zeroed global and static variables. + ld bc, #l__DATA + ld a, b + or a, c + jr Z, zeroed_data + ld hl, #s__DATA + ld (hl), #0x00 + dec bc + ld a, b + or a, c + jr Z, zeroed_data + ld e, l + ld d, h + inc de + ldir +zeroed_data: + + ; Explicitly initialized global variables. + ld bc, #l__INITIALIZER + ld a, b + or a, c + jr Z, gsinit_static + ld de, #s__INITIALIZED + ld hl, #s__INITIALIZER + ldir + +gsinit_static: + ; Explicitly initialized static variables inserted by compiler here. + + .area _GSFINAL + ret + + .area _HOME + diff --git a/src/worker/lib/cpc/crt0-cpc.sym b/src/worker/lib/cpc/crt0-cpc.sym new file mode 100644 index 00000000..aecdcbbb --- /dev/null +++ b/src/worker/lib/cpc/crt0-cpc.sym @@ -0,0 +1,27 @@ + ASxxxx Assembler V02.00 + NoICE + SDCC mods (Zilog Z80 / Hitachi HD64180), page 1. +Hexadecimal [16-Bits] + +Symbol Table + + .__.$$$.= 2710 L | .__.ABS.= 0000 G | .__.CPU.= 0000 L + .__.H$L.= 0000 L | 0 _Start 0000 R | ___sdcc_ **** GX + _main **** GX | 3 gsinit 0000 GR | 3 gsinit_s 0025 R + l__DATA **** GX | l__INITI **** GX | s__DATA **** GX + s__INITI **** GX | s__INITI **** GX | 3 zeroed_d 0016 R + + ASxxxx Assembler V02.00 + NoICE + SDCC mods (Zilog Z80 / Hitachi HD64180), page 2. +Hexadecimal [16-Bits] + +Area Table + + 0 _CODE size A flags 0 + 1 _INITIAL size 0 flags 0 + 2 _HOME size 0 flags 0 + 3 _GSINIT size 25 flags 0 + 4 _GSFINAL size 1 flags 0 + 5 _DATA size 0 flags 0 + 6 _INITIAL size 0 flags 0 + 7 _BSEG size 0 flags 0 + 8 _BSS size 0 flags 0 + 9 _HEAP size 0 flags 0 + diff --git a/src/worker/workermain.ts b/src/worker/workermain.ts index 7fca1166..a21df23b 100644 --- a/src/worker/workermain.ts +++ b/src/worker/workermain.ts @@ -331,12 +331,12 @@ var PLATFORM_PARAMS = { 'zx': { arch: 'z80', code_start: 0x5ccb, - rom_size: 0xff58-0x5ccb, + rom_size: 0xff58-0x5ccb, data_start: 0xf000, - data_size: 0xfe00-0xf000, - stack_end: 0xff58, - extra_link_args: ['crt0-zx.rel'], - extra_link_files: ['crt0-zx.rel', 'crt0-zx.lst'], + data_size: 0xfe00-0xf000, + stack_end: 0xff58, + extra_link_args: ['crt0-zx.rel'], + extra_link_files: ['crt0-zx.rel', 'crt0-zx.lst'], }, 'devel-6502': { arch: '6502', @@ -344,6 +344,18 @@ var PLATFORM_PARAMS = { libargs: ['crt0.o', 'sim6502.lib'], extra_link_files: ['crt0.o', 'devel-6502.cfg'], }, + // https://github.com/cpcitor/cpc-dev-tool-chain + 'cpc': { + arch: 'z80', + code_start: 0x4000, + rom_size: 0xb100-0x4000, + data_start: 0xb100, + data_size: 0xb100-0xc000, + stack_end: 0xc000, + extra_compile_files: ['cpcrslib.h'], + extra_link_args: ['crt0-cpc.rel', 'cpcrslib.lib'], + extra_link_files: ['crt0-cpc.rel', 'crt0-cpc.lst', 'cpcrslib.lib', 'cpcrslib.lst'], + }, }; PLATFORM_PARAMS['sms-sms-libcv'] = PLATFORM_PARAMS['sms-sg1000-libcv'];