cpc: cpctelera, start @ 0x4000, new vsync

This commit is contained in:
Steven Hugg 2021-12-01 15:08:33 -06:00
parent 68320b8ee9
commit c3403a0506
21 changed files with 11914 additions and 127 deletions

View File

@ -60,6 +60,7 @@ The IDE uses custom forks for many of these, found at https://github.com/sehugg?
* https://github.com/DrGoldfire/Z80.js
* http://www.twitchasylum.com/jsvecx/
* https://github.com/curiousdannii/ifvms.js/
* https://6502ts.github.io/typedoc/stellerator-embedded/
### Compilers
@ -87,6 +88,7 @@ The IDE uses custom forks for many of these, found at https://github.com/sehugg?
* https://shiru.untergrund.net/code.shtml
* http://www.colecovision.eu/ColecoVision/development/libcv.shtml
* https://github.com/toyoshim/tss
* https://github.com/lronaldo/cpctelera
### Firmware

View File

@ -168,6 +168,7 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
<li><a class="dropdown-item" href="?platform=apple2">Apple ][+</a></li>
<li><a class="dropdown-item" href="?platform=zx">ZX Spectrum</a></li>
<li><a class="dropdown-item" href="?platform=x86">x86 (FreeDOS)</a></li>
<li><a class="dropdown-item" href="?platform=cpc.6128">Amstrad CPC6128</a></li>
</ul>
</li>
<li class="dropdown dropdown-submenu">

View File

@ -0,0 +1,153 @@
//-----------------------------LICENSE NOTICE------------------------------------
// This file is part of CPCtelera: An Amstrad CPC Game Engine
// Copyright (C) 2015 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------
#include "cpctelera.h"
// Constant to set the number of VSYNCs to wait for as a delay between
// each pair of strings drawn. This will let as see how they are
// drawn, making it a little bit slower.
// - WFRAMES = 3 (Work at 12.5 FPS (50/3))
#define WFRAMES 3
//
// Wait n complete screen frames of (1/50)s
//
void wait_frames(u16 nframes) {
u16 i, j; // frame counter and active wait loop counter
// Loop for nframe times, waiting for VSYNC
for (i=0; i < nframes; i++) {
cpct_waitVSYNC();
// VSYNC is usually active for ~1500 cycles, then we have to do
// something that takes approximately this amount of time before
// waiting for the next VSYNC, or we will find the same VSYNC signal
// This active wait loop will do at least 750 comparisons, what
// is the same as 750*4 cycles (at least)
for (j=0; j < 750; j++);
}
}
//
// Strings Example: Main program
//
void main(void) {
u8 *pvideomem; // Pointer to the video memory location where strings will be drawn
u8 times; // Counter of number of times to draw
u8 colours[5] = {0}; // 5 Colour values, 1 for mode 2, 2 for mode 1 and 2 more for mode 0
// First, disable firmware to prevent it from restoring video modes and
// interfering with drawString functions
cpct_disableFirmware();
// Loop forever showing characters on different modes and colours
//
while(1) {
//
// Show some strings in Mode 0, using different colours
//
// Clear Screen filling it up with 0's and set mode 0
cpct_disableFirmware();
cpct_disableUpperROM();
cpct_clearScreen(0);
cpct_setVideoMode(0);
// Let's start drawing strings at the start of video memory (0xC000)
pvideomem = CPCT_VMEM_START;
// Draw 25 strings, 1 for each character line on the screen
for (times=0; times < 25; times++) {
// Pick up the next foreground colour available for next string
// rotating colours when the 16 available have been used
// We use module 16 (AND 0x0F) for faster calculations
colours[0] = ++colours[0] & 15;
// Draw the string and wait for some VSYNCs
cpct_drawStringM0("$ Mode 0 string $", pvideomem, colours[0], colours[3]);
wait_frames(WFRAMES);
// Point to the start of the next character line on screen (80 bytes away)
pvideomem += 0x50;
}
// Rotate background colour for next time we draw Mode 0 strings
colours[3] = ++colours[3] & 15;
//
// Show some strings in Mode 1, using different colours
//
// Clear Screen filling it up with 0's and set mode 1
cpct_clearScreen(0);
cpct_setVideoMode(1);
// Let's start drawing strings at the start of video memory (0xC000)
pvideomem = CPCT_VMEM_START;
// Draw 25 strings, 1 for each character line on the screen
for (times=0; times < 25; times++) {
// Rotate foreground colour using module 4 (AND 0x03)
colours[1] = ++colours[1] & 3;
// Draw a string using normal drawString function for mode 1
cpct_drawStringM1("Mode 1 string :D", pvideomem, colours[1], colours[4]);
// Rotate foreground colour again
colours[1] = ++colours[1] & 3;
// Draw a string using fast drawString function for mode 1 (in a column 38 bytes to the right)
cpct_drawStringM1_f("Mode 1 string (Fast)", pvideomem + 38, colours[1], colours[4]);
// Rotate foreground colour another time and wait for a few VSYNCs
colours[1] = ++colours[1] & 3;
wait_frames(WFRAMES);
// Point to the start of the next character line on screen (80 bytes away)
pvideomem += 0x50;
}
colours[4] = ++colours[4] & 3;
//
// Show some strings in Mode 2, using different colours
//
// Clear Screen filling it up with 0's and set mode 2
cpct_clearScreen(0);
cpct_setVideoMode(2);
// Let's start drawing strings at the start of video memory (0xC000)
pvideomem = CPCT_VMEM_START;
// Draw 25 strings, 1 for each character line on the screen
for (times=0; times < 25; times++) {
// Alternate between foreground colour or inverse colour (the only 2
// available on mode 2) using an XOR 1 operation that alternates the
// value between 0 and 1
colours[2] ^= 1;
// Draw string on the screen using current colour and wait for a few VSYNCs
cpct_drawStringM2("And, finally, this is a long mode 2 string!!", pvideomem, colours[2]);
wait_frames(WFRAMES);
// Point to the start of the next character line on screen (80 bytes away)
pvideomem += 0x50;
}
}
}

103
presets/cpc/easy_random.c Normal file
View File

@ -0,0 +1,103 @@
//-----------------------------LICENSE NOTICE------------------------------------
// This file is part of CPCtelera: An Amstrad CPC Game Engine
// Copyright (C) 2016 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------
#include "cpctelera.h"
#include <stdio.h>
// Total random numbers to show (up to 255)
#define N_RND_NUMBERS 50
//////////////////////////////////////////////////////////////////
// wait4UserKeypress
// Waits till the user presses a key, counting the number of
// loop iterations passed.
//
// Returns:
// <u32> Number of iterations passed
//
u32 wait4UserKeypress() {
u32 c = 0; // Count the number of cycles passed till user k
// Wait 'till the user presses a key, counting loop iterations
do {
c++; // One more cycle
cpct_scanKeyboard_f(); // Scan the scan the keyboard
} while ( ! cpct_isAnyKeyPressed_f() );
return c;
}
//////////////////////////////////////////////////////////////////
// initialize
// Shows introductory messages and initializes the pseudo-random
// number generator
//
void initialize() {
u32 seed; // Value to initialize the random seed
// Introductory message
printf("\017\003========= BASIC RANDOM NUMBERS =========\n\n\r");
printf("\017\002Press any key to generate random numbers\n\n\r");
// Wait till the users presses a key and use the number of
// passed cycles as random seed for the Random Number Generator
seed = wait4UserKeypress();
// Random seed may never be 0, so check first and add 1 if it was 0
if (!seed)
seed++;
// Print the seed and seed the random number generator
printf("\017\003Selected seed: \017\002%d\n\r", seed);
cpct_srand8(seed);
}
//////////////////////////////////////////////////////////////////
// printRandomNumbers
// Prints some random numbers in the screen, as requested.
// INPUT:
// nNumbers - Total amount of pseudo-random numbers to print
//
void printRandomNumbers(u8 nNumbers) {
// Anounce numbers
printf("\017\003Generating \017\002%d\017\003 random numbers\n\n\r\017\001", N_RND_NUMBERS);
// Count from nNumbers to 0, printing random numbers
while (nNumbers--) {
u8 random_number = cpct_rand(); // Get next random number
printf("%d ", random_number); // Print it
}
// End printing with newlines
printf("\n\n\r");
}
//////////////////////////////////////////////////////////////////
// MAIN ENTRY POINT OF THE APPLICATION
//
void main(void) {
// Loop forever
while (1) {
// Initialize everything and print some random numbers
initialize();
printRandomNumbers(N_RND_NUMBERS);
// Wait 'till the user stops pressing a key
do { cpct_scanKeyboard_f(); } while ( cpct_isAnyKeyPressed_f() );
}
}

154
presets/cpc/easy_sprites.c Normal file
View File

@ -0,0 +1,154 @@
//-----------------------------LICENSE NOTICE------------------------------------
// This file is part of CPCtelera: An Amstrad CPC Game Engine
// Copyright (C) 2014-2015 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR)
// Copyright (C) 2015 Maximo / Cheesetea / ByteRealms (@rgallego87)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------
#include "cpctelera.h"
// Declare sprites and palette, without defining them
// Palette for Cheesetea's Sprite Logo
extern const u8 G_palette[4];
// Cheesetea's Sprite Logo, by Maximo (@rgallego87)
extern const u8 G_spriteLogoCT[744];
// Sprite size (in bytes)
#define SP_W 12
#define SP_H 62
// Screen size (in bytes)
#define SCR_W 80
#define SCR_H 200
//
// MAIN: Using keyboard to move a sprite example
//
void main(void) {
u8 x=10, y=10; // Sprite coordinates
u8* pvideomem; // Pointer to video memory
//
// Set up the screen
//
// Disable firmware to prevent it from interfering with setPalette and setVideoMode
cpct_disableFirmware();
// Set the colour palette
cpct_fw2hw (G_palette, 4); // Convert our palette from firmware to hardware colours
cpct_setPalette(G_palette, 4); // Set up the hardware palette using hardware colours
// Set video mode 1 (320x200, 4 colours)
cpct_setVideoMode(1);
//
// Infinite moving loop
//
while(1) {
// Scan Keyboard (fastest routine)
// The Keyboard has to be scanned to obtain pressed / not pressed status of
// every key before checking each individual key's status.
cpct_scanKeyboard_f();
// Check if user has pressed a Cursor Key and, if so, move the sprite if
// it will still be inside screen boundaries
if (cpct_isKeyPressed(Key_CursorRight) && x < (SCR_W - SP_W) ) ++x;
else if (cpct_isKeyPressed(Key_CursorLeft) && x > 0 ) --x;
if (cpct_isKeyPressed(Key_CursorUp) && y > 0 ) --y;
else if (cpct_isKeyPressed(Key_CursorDown) && y < (SCR_H - SP_H) ) ++y;
// Get video memory byte for coordinates x, y of the sprite (in bytes)
pvideomem = cpct_getScreenPtr(CPCT_VMEM_START, x, y);
// Draw the sprite in the video memory location got from coordinates x, y
cpct_drawSprite(G_spriteLogoCT, pvideomem, SP_W, SP_H);
}
}
//
// Definitions of the sprites and palette
//
// Palete for mode 1 (4 firmware colours)
const u8 G_palette[4] = { 0x00, 0x18, 0x1A, 0x0D };
// Sprite definition of the Cheesetea Logo, by Maximo (@rgallego87).
const u8 G_spriteLogoCT[744] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x11,0x9F,0x88,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x23,0x0F,0x4C,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x47,0x0F,0x2E,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x47,0x0F,0x2E,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x03,0x4F,0x0F,0x3F,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x37,0xCF,0x0F,0x2F,0x88,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x7F,0xCF,0x0F,0x2F,0x4C,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x7F,0xCF,0x0F,0x4F,0x4C,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x7F,0x0F,0x1F,0xCF,0x4C,0x00,0x00,0x00,
0x00,0x00,0x00,0x01,0x6F,0x0F,0x1F,0xEF,0x2E,0x00,0x00,0x00,
0x00,0x00,0x00,0x13,0xEF,0x0F,0x1F,0xEF,0x1F,0x00,0x00,0x00,
0x00,0x00,0x00,0x13,0xEF,0x0F,0x1F,0xEF,0x1F,0x00,0x00,0x00,
0x00,0x00,0x00,0x13,0xEF,0x0F,0x1F,0xEF,0x1F,0x00,0x00,0x00,
0x00,0x00,0x00,0x13,0xEF,0x0F,0x0F,0x6F,0x1F,0x00,0x00,0x00,
0x00,0x00,0x00,0x01,0xFF,0x0F,0x0F,0x2F,0x3F,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x7F,0xCF,0x0F,0x2F,0x4C,0x00,0x00,0x00,
0x00,0x00,0x00,0x33,0x7F,0xCF,0x0F,0x2F,0x4F,0x00,0x00,0x00,
0x00,0x00,0x00,0x23,0x7F,0xCF,0x0F,0x2F,0x6F,0x00,0x00,0x00,
0x00,0x00,0x00,0x23,0x7F,0xCF,0x0F,0x3F,0x6F,0x00,0x00,0x00,
0x00,0x00,0x00,0x47,0x1F,0xEF,0x0F,0x0F,0xFF,0x08,0x00,0x00,
0x00,0x00,0x00,0x8F,0x1F,0xEF,0x0F,0x0F,0xFF,0x8C,0x00,0x00,
0x00,0x00,0x00,0xBC,0xF0,0xF0,0xF0,0xF0,0xF0,0x8C,0x00,0x00,
0x00,0x00,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xC0,0x00,
0x00,0x10,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xE0,0x00,
0x00,0x10,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xC0,0x00,
0x00,0x10,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0x80,0x00,
0x00,0x30,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0x00,0x00,
0x00,0x30,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xE0,0x00,0x00,
0x00,0x30,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xC0,0x00,0x00,
0x00,0x30,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0x80,0x00,0x00,
0x00,0x30,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,
0x00,0x30,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xE0,0x00,0x00,0x00,
0x00,0x70,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xC0,0x00,0x00,0x00,
0x00,0x70,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0x80,0x00,0x00,0x00,
0x00,0x70,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,
0x00,0x70,0xF0,0xF0,0xF0,0xF0,0xF0,0xE0,0x00,0x00,0x00,0x00,
0x00,0x70,0xF0,0xF0,0xF0,0xF0,0xF0,0xC0,0x00,0x00,0x00,0x00,
0x00,0x70,0xF0,0xF0,0xF0,0xF0,0xF0,0x80,0x00,0x00,0x00,0x00,
0x00,0x70,0xF0,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,
0x00,0x70,0xF0,0xF0,0xF0,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,
0x00,0x70,0xF0,0xF0,0xF0,0xF0,0xC0,0x00,0x00,0x00,0x00,0x00,
0x00,0x70,0xF0,0xF0,0xF0,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,
0x00,0x70,0xF0,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,
0x00,0x70,0xF0,0xF0,0xF0,0xF0,0xF0,0x80,0x00,0x00,0x00,0x00,
0x00,0x70,0xF0,0xF0,0xF0,0xF0,0xF0,0xC0,0x00,0x00,0x00,0x00,
0x00,0x70,0xF0,0xF0,0xF0,0xF0,0xF0,0xE0,0x00,0x00,0x00,0x00,
0x00,0x70,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,
0x00,0x70,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0x80,0x00,0x00,0x00,
0x00,0x70,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xC0,0x00,0x00,0x00,
0x00,0x30,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xE0,0x00,0x00,0x00,
0x00,0x30,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0x80,0x00,0x00,
0x00,0x30,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xC0,0x00,0x00,
0x00,0x30,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xE0,0x00,0x00,
0x00,0x30,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0x00,0x00,
0x00,0x30,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0x80,0x00,
0x00,0x10,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xC0,0x00,
0x00,0x10,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xE0,0x00,
0x00,0x10,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xE0,0x00,
0x00,0x00,0x70,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0x80,0x00,
0x00,0x00,0x00,0x30,0xF0,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};

View File

@ -0,0 +1,80 @@
//-----------------------------LICENSE NOTICE------------------------------------
// This file is part of CPCtelera: An Amstrad CPC Game Engine
// Copyright (C) 2015 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------
#include "cpctelera.h"
#include <stdio.h>
#include <string.h>
//
// MAIN PROGRAM:
// Do not disable firmware in this example, as printf makes use of it through putchar
//
void main(void) {
// Needed for screen clear to work
cpct_disableFirmware ();
cpct_disableUpperROM ();
// Clear Screen filling it up with 0's
cpct_clearScreen(0);
// Print out some messages using printf and sizeof to know the sizes in bytes
// ...of all the builting types in SDCC (using CPCtelera's aliases)
// We use Firmware Screen Character Commands to change colour on screen.
// Printing \0XX is equivalent to printing the character XX (in octal).
// Character 15 (017 in octal) does the PEN command, and uses immediate next
// character as the parameter for PEN. Then, \017\003 is equivalent to PEN 3.
//
printf(" \017\003Welcome to \017\002CPCtelera\017\003!\017\001\n\r\n\r");
printf("This example makes use of standard C");
printf("libraries to print out byte sizes of");
printf("standard SDCC types, using \017\002CPCtelera\017\001's");
printf("convenient aliases.\n\r\n\r");
printf("Size of \017\003 u8 \017\001=\017\002 %d \017\001byte\n\r", sizeof(u8));
printf("Size of \017\003u16 \017\001=\017\002 %d \017\001byte\n\r", sizeof(u16));
printf("Size of \017\003u32 \017\001=\017\002 %d \017\001byte\n\r", sizeof(u32));
printf("Size of \017\003u64 \017\001=\017\002 %d \017\001byte\n\r", sizeof(u64));
printf("Size of \017\003 i8 \017\001=\017\002 %d \017\001byte\n\r", sizeof(i8));
printf("Size of \017\003i16 \017\001=\017\002 %d \017\001byte\n\r", sizeof(i16));
printf("Size of \017\003i32 \017\001=\017\002 %d \017\001byte\n\r", sizeof(i32));
printf("Size of \017\003i64 \017\001=\017\002 %d \017\001byte\n\r", sizeof(i64));
printf("Size of \017\003f32 \017\001=\017\002 %d \017\001byte\n\r", sizeof(f32));
// cpct_disableFirmware ();
cpct_disableUpperROM ();
// 2 boxes with varying colour patterns
cpct_drawSolidBox((u8*)0xC265, cpct_px2byteM1(1, 0, 2, 1), 10, 20);
cpct_drawSolidBox((u8*)0xC275, cpct_px2byteM1(0, 2, 0, 1), 10, 20);
// 2 stripped boxes in 2 alternating colours
cpct_drawSolidBox((u8*)0xC355, 0xA0, 10, 20); // 0xA0 = cpct_px2byteM1(1, 0, 1, 0)
cpct_drawSolidBox((u8*)0xC365, 0x0A, 10, 20); // 0x0A = cpct_px2byteM1(2, 0, 2, 0)
// Another 2 stripped boxes, with the strips displaced
cpct_drawSolidBox((u8*)0xC445, 0x50, 10, 20); // 0x50 = cpct_px2byteM1(0, 1, 0, 1)
cpct_drawSolidBox((u8*)0xC455, 0x05, 10, 20); // 0x05 = cpct_px2byteM1(0, 2, 0, 2)
// 2 Boxes in solid colour (4 pixels of the same colour)
cpct_drawSolidBox((u8*)0xC535, cpct_px2byteM1(2, 2, 2, 2), 10, 20); // 0xF0
cpct_drawSolidBox((u8*)0xC545, cpct_px2byteM1(1, 1, 1, 1), 10, 20); // 0x0F
// Loop forever
while (1);
}

View File

@ -0,0 +1,119 @@
//-----------------------------LICENSE NOTICE------------------------------------
// This file is part of CPCtelera: An Amstrad CPC Game Engine
// Copyright (C) 2015 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR)
// Created in collaboration with Roald Strauss (aka mr_lou / CPCWiki)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------
#include "cpctelera.h"
#include <string.h>
// Useful constants
// * Start of screen video memory
// * Size in bytes of a complete screen video pixel line
// * Offset from the start of a pixel line to the start of the next (inside same group of 8 pixel lines)
// * Screen character line to be used for scrolling (0-24)
#define PIXEL_LINE_SIZE 0x0050
#define PIXEL_LINE_OFFSET 0x0800
#define CHARLINE 12
//
// Waits n times for a VSYNC signal (1/50s). After each VSYNC signal,
// if waits for 2 interrupts (using HALT 2 times) to ensure that VSYNC
// stops being active until looking for the next VSYNC signal.
//
void wait_n_VSYNCs(u8 n) {
do {
// Wait for 1 VSYNC signal
cpct_waitVSYNC();
// If we still have to wait for more VSYNC signals, wait first
// for this present VSYNC signal to become inactive. For that,
// wait for 2 system interrupts using ASM halt instruction.
if (--n) {
__asm__("halt");
__asm__("halt");
}
} while(n);
}
//
// Scrolls a Character line (8 pixel lines) 1 byte to the left. To do
// this, it goes byte by byte copying the next byte (the one to the right)
// pCharline: pointer to the first byte of the character line (the 8 pixel lines)
// lineSize: number of total bytes a pixel line has
//
void scrollLine(u8* pCharline, u16 lineSize) {
// Scroll 8 pixel lines. This loop is executed 8 times: when pCharline is incremented
// the 9th time, it will overflow (will be greater than 0xFFFF, cycling through 0x0000)
// and will be lower than 0xC000.
for (; pCharline > CPCT_VMEM_START; pCharline += PIXEL_LINE_OFFSET)
cpct_memcpy(pCharline, pCharline+1, lineSize);
}
//
// MAIN LOOP
//
void main(void) {
// Test to be used for scrolling (declared constant as it won't be modified,
// and that prevents compiler from generating code for initializing it)
const u8 *text="This is a simple software scrolling mode 1 text. Not really smooth, but easy to understand. ";
// Pointer to the first byte of the screen character line
// (8 pixel lines) to be scrolled. First 25 pixel lines of screen
// video memory are the 25 pixel 0 lines of each screen character line
// (group of 8 pixel lines), hence this calculation.
u8* pCharline_start = CPCT_VMEM_START + (PIXEL_LINE_SIZE * CHARLINE);
// Pointer to the first byte of the last screen character of the
// character line (last 2 bytes of the 8 pixel lines)
const u8* pNextCharLocation = pCharline_start + PIXEL_LINE_SIZE - 2;
const u8 textlen=strlen(text); // Save the lenght of the text for later use
u8 nextChar=0; // Next character of the text to be drawn on the screen
u8 penColour=1; // Pen colour for the characters
cpct_disableFirmware ();
cpct_disableUpperROM ();
// Infinite scrolling loop
cpct_drawStringM1("Hold any key to pause scroll", CPCT_VMEM_START, 1, 3);
while (1) {
// When holding a key, wait for release (Loop scanning the keyboard
// until no single key is pressed)
do { cpct_scanKeyboard_f(); } while( cpct_isAnyKeyPressed_f() );
// Draw next character at the rightmost character location of the
// character line being scrolled
cpct_drawCharM1_f(pNextCharLocation, penColour, 0, text[nextChar]);
// nextChar will hold the index of the next Character, returning to
// the first one when there are no more characters left, and changing
// Pen colour for next sentence
if (++nextChar == textlen) {
nextChar = 0;
if (++penColour > 3) penColour = 1;
}
// Scroll character line 2 times, as each scroll call will move
// the pixels 1 byte = 4 pixels. So, 2 times = 8 pixels = 1 Character
// Sinchronyze with VSYNC previous to each call to make it smooth
wait_n_VSYNCs(2);
scrollLine(pCharline_start, PIXEL_LINE_SIZE);
wait_n_VSYNCs(2);
scrollLine(pCharline_start, PIXEL_LINE_SIZE);
}
}

23
presets/cpc/skeleton.sdcc Normal file
View File

@ -0,0 +1,23 @@
#include "cpctelera.h"
#include <stdio.h>
#include <string.h>
void main(void) {
// Needed for screen clear to work
cpct_disableFirmware ();
cpct_disableUpperROM ();
// Clear Screen filling it up with 0's
cpct_clearScreen(0);
// Print out some messages using printf
printf("\017\003Hello \017\002World!\n\r");
// printf() may have enabled upper ROM, disable
cpct_disableUpperROM ();
// Loop forever
while (1);
}

Binary file not shown.

View File

@ -82,7 +82,7 @@ export class C64_WASMMachine extends BaseWASMMachine implements Machine, Probeab
var clocks = Math.floor((this.numTotalScanlines - scanline) * (19656+295) / this.numTotalScanlines);
var probing = this.probe != null;
if (probing) this.exports.machine_reset_probe_buffer();
var clocks = super.advanceFrameClock(trap, clocks);
clocks = super.advanceFrameClock(trap, clocks);
if (probing) this.copyProbeData();
return clocks;
}

View File

@ -32,15 +32,15 @@ export class CPC_WASMMachine extends BaseWASMMachine implements Machine {
cpuCyclesPerLine = 224;
joymask0 = 0;
runaddr = 0x4000;
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[26] = this.runaddr & 0xff;
combined[27] = this.runaddr >> 8;
combined.set(rom, BIN_HEADER.length);
super.loadROM(combined);
}
@ -51,13 +51,18 @@ export class CPC_WASMMachine extends BaseWASMMachine implements Machine {
// load rom (SNA or BIN)
if (this.romptr && this.romlen) {
this.exports.machine_load_rom(this.sys, this.romptr, this.romlen);
// advance clock until program starts
for (var i=0; i<100000 && this.getPC() != this.runaddr; i++) {
this.exports.machine_tick(this.sys);
}
}
}
advanceFrame(trap: TrapCondition) : number {
//var scanline = this.exports.machine_get_raster_line(this.sys);
var scanline = this.exports.machine_get_raster_line(this.sys);
var clocks = Math.floor((this.numTotalScanlines - scanline) * 19965 / this.numTotalScanlines);
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
clocks = super.advanceFrameClock(trap, clocks);
if (probing) this.copyProbeData();
return clocks;
}
@ -117,7 +122,6 @@ export class CPC_WASMMachine extends BaseWASMMachine implements Machine {
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
@ -141,6 +145,6 @@ export class CPC_WASMMachine extends BaseWASMMachine implements Machine {
this.exports.machine_key_up(this.sys, key);
this.joymask0 &= ~mask;
}
this.exports.cpc_joystick(this.sys, this.joymask0, 0);
// TODO: this.exports.cpc_joystick(this.sys, this.joymask0, 0);
}
}

View File

@ -5,8 +5,13 @@ 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)'},
{id:'easy_stdio_boxes.c', name:'Standard I/O (C)'},
{id:'easy_mode_strings.c', name:'Video Modes (C)'},
{id:'easy_random.c', name:'Random Numbers (C)'},
{id:'easy_sprites.c', name:'Keyboard + Sprites (C)'},
{id:'medium_scrolling.c', name:'Scrolling Text (C)'},
//{id:'sprite_demo.c', name:'Sprite Demo (C)'},
//{id:'keyboard_redefine.c', name:'Keyboard Redefine (C)'},
];
const CPC_MEMORY_MAP = { main:[
@ -24,8 +29,11 @@ class CPCWASMPlatform extends BaseZ80MachinePlatform<CPC_WASMMachine> implements
readAddress(a) { return this.machine.readConst(a); }
getMemoryMap() { return CPC_MEMORY_MAP; }
showHelp() {
window.open("https://worldofspectrum.org/faq/reference/reference.htm", "_help");
window.open("http://lronaldo.github.io/cpctelera/files/readme-txt.html", "_help");
}
}
// TODO: make different cpc_init() types for different platforms
PLATFORMS['cpc.6128'] = CPCWASMPlatform;
PLATFORMS['cpc.464'] = CPCWASMPlatform;
PLATFORMS['cpc.kcc'] = CPCWASMPlatform;

View File

@ -0,0 +1,3 @@
crt0-cpc.rel:
/opt/homebrew/bin/sdasz80 -los crt0-cpc.s

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@

View File

@ -1,75 +1,80 @@
ASxxxx Assembler V02.00 + NoICE + SDCC mods (Zilog Z80 / Hitachi HD64180), page 1.
Hexadecimal [16-Bits]
ASxxxx Assembler V02.00 + NoICE + SDCC mods (Zilog Z80 / Hitachi HD64180 / ZX-Next / eZ80), page 1.
Hexadecimal [24-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]
1 ; crt0.s for ZX Spectrum
2
3 .module crt0
4 .globl _main
5 .globl ___sdcc_call_hl
6 .globl l__DATA
7 .globl s__DATA
8 .globl s__INITIALIZED
9 .globl s__INITIALIZER
10 .globl l__INITIALIZER
11
12 ; Ordering of segments for the linker - copied from sdcc crt0.s
13 .area _CODE
14 .area _INITIALIZER
15 .area _HOME
16 .area _GSINIT
17 .area _GSFINAL
18 .area _DATA
19 .area _INITIALIZED
20 .area _BSEG
21 .area _BSS
22 .area _HEAP
23
24 .area _CODE
25
000000 26 _Start:
27 ;di
28 ;im 1
29 ; stack pointer already set by BIOS
000000 CD 00 00 [17] 30 call gsinit ; Initialize global and static variables.
000003 CD 00 00 [17] 31 call _main
000006 C7 [11] 32 rst 0x0 ; Restart when main() returns.
33
34 .area _GSINIT
000000 35 gsinit::
36
37 ; Implicitly zeroed global and static variables.
000000 01 00 00 [10] 38 ld bc, #l__DATA
000003 78 [ 4] 39 ld a, b
000004 B1 [ 4] 40 or a, c
000005 28 0F [12] 41 jr Z, zeroed_data
000007 21 00 00 [10] 42 ld hl, #s__DATA
00000A 36 00 [10] 43 ld (hl), #0x00
00000C 0B [ 6] 44 dec bc
00000D 78 [ 4] 45 ld a, b
00000E B1 [ 4] 46 or a, c
00000F 28 05 [12] 47 jr Z, zeroed_data
000011 5D [ 4] 48 ld e, l
000012 54 [ 4] 49 ld d, h
000013 13 [ 6] 50 inc de
000014 ED B0 [21] 51 ldir
000016 52 zeroed_data:
53
54 ; Explicitly initialized global variables.
000016 01 00 00 [10] 55 ld bc, #l__INITIALIZER
ASxxxx Assembler V02.00 + NoICE + SDCC mods (Zilog Z80 / Hitachi HD64180 / ZX-Next / eZ80), page 2.
Hexadecimal [24-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
000019 78 [ 4] 56 ld a, b
00001A B1 [ 4] 57 or a, c
00001B 28 08 [12] 58 jr Z, gsinit_static
00001D 11 00 00 [10] 59 ld de, #s__INITIALIZED
000020 21 00 00 [10] 60 ld hl, #s__INITIALIZER
000023 ED B0 [21] 61 ldir
62
000025 63 gsinit_static:
64 ; Explicitly initialized static variables inserted by compiler here.
65
66 .area _GSFINAL
000000 C9 [10] 67 ret
68
69 .area _HOME
70

View File

@ -1,42 +1,42 @@
XL2
XL3
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
S l__DATA Ref000000
S _main Ref000000
S s__DATA Ref000000
S .__.ABS. Def000000
S s__INITIALIZED Ref000000
S ___sdcc_call_hl Ref000000
S l__INITIALIZER Ref000000
S s__INITIALIZER Ref000000
A _CODE size 7 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
S gsinit Def000000
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
T 00 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
T 00 00 00 CD 00 00 CD 00 00 C7
R 00 00 00 00 00 04 03 00 02 07 01 00
T 00 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
T 00 00 00 01 00 00 78 B1 28 0F 21 00 00 36 00 0B
R 00 00 03 00 02 04 00 00 02 0B 02 00
T 0D 00 00 78 B1 28 05 5D 54 13 ED B0
R 00 00 03 00
T 16 00
T 16 00 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
T 16 00 00 01 00 00 78 B1 28 08 11 00 00 21 00 00
R 00 00 03 00 02 04 06 00 02 0B 04 00 02 0E 07 00
T 23 00 00 ED B0
R 00 00 03 00
T 25 00
T 25 00 00
R 00 00 03 00
T 00 00 C9
T 00 00 00 C9
R 00 00 04 00

View File

@ -3,6 +3,11 @@
.module crt0
.globl _main
.globl ___sdcc_call_hl
.globl l__DATA
.globl s__DATA
.globl s__INITIALIZED
.globl s__INITIALIZER
.globl l__INITIALIZER
; Ordering of segments for the linker - copied from sdcc crt0.s
.area _CODE
@ -19,8 +24,8 @@
.area _CODE
_Start:
di
im 1
;di
;im 1
; stack pointer already set by BIOS
call gsinit ; Initialize global and static variables.
call _main
@ -34,7 +39,7 @@ gsinit::
ld a, b
or a, c
jr Z, zeroed_data
ld hl, #s__DATA
ld hl, #s__DATA
ld (hl), #0x00
dec bc
ld a, b

View File

@ -1,27 +1,27 @@
ASxxxx Assembler V02.00 + NoICE + SDCC mods (Zilog Z80 / Hitachi HD64180), page 1.
Hexadecimal [16-Bits]
ASxxxx Assembler V02.00 + NoICE + SDCC mods (Zilog Z80 / Hitachi HD64180 / ZX-Next / eZ80), page 1.
Hexadecimal [24-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
.__.$$$.= 002710 L | .__.ABS.= 000000 G | .__.CPU.= 000000 L
.__.H$L.= 000000 L | 0 _Start 000000 R | ___sdcc_ ****** GX
_main ****** GX | 3 gsinit 000000 GR | 3 gsinit_s 000025 R
l__DATA ****** GX | l__INITI ****** GX | s__DATA ****** GX
s__INITI ****** GX | s__INITI ****** GX | 3 zeroed_d 000016 R
ASxxxx Assembler V02.00 + NoICE + SDCC mods (Zilog Z80 / Hitachi HD64180), page 2.
Hexadecimal [16-Bits]
ASxxxx Assembler V02.00 + NoICE + SDCC mods (Zilog Z80 / Hitachi HD64180 / ZX-Next / eZ80), page 2.
Hexadecimal [24-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
0 _CODE size 7 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

View File

@ -345,7 +345,7 @@ var PLATFORM_PARAMS = {
extra_link_files: ['crt0.o', 'devel-6502.cfg'],
},
// https://github.com/cpcitor/cpc-dev-tool-chain
'cpc': {
'cpc.rslib': {
arch: 'z80',
code_start: 0x4000,
rom_size: 0xb100-0x4000,
@ -356,6 +356,18 @@ var PLATFORM_PARAMS = {
extra_link_args: ['crt0-cpc.rel', 'cpcrslib.lib'],
extra_link_files: ['crt0-cpc.rel', 'crt0-cpc.lst', 'cpcrslib.lib', 'cpcrslib.lst'],
},
// https://lronaldo.github.io/cpctelera/ (TODO)
'cpc': {
arch: 'z80',
code_start: 0x4000,
rom_size: 0xb100-0x4000,
data_start: 0xb100,
data_size: 0xb100-0xc000,
stack_end: 0xc000,
extra_compile_files: ['cpctelera.h'],
extra_link_args: ['crt0-cpc.rel', 'cpctelera.lib'],
extra_link_files: ['crt0-cpc.rel', 'crt0-cpc.lst', 'cpctelera.lib', 'cpctelera.lst'],
},
};
PLATFORM_PARAMS['sms-sms-libcv'] = PLATFORM_PARAMS['sms-sg1000-libcv'];