sg1000 platform + libcv 0.24.2

This commit is contained in:
Steven Hugg 2018-11-28 10:31:07 -05:00
parent 79638ad01e
commit c2a6417e28
37 changed files with 9303 additions and 11 deletions

View File

@ -84,6 +84,7 @@ TODO:
- what if .c and .s names collide?
- live coding URL
- memory viewer: ROM/RAM/VRAM/etc
- resize memory browser when split resize
WEB WORKER FORMAT

View File

@ -23,8 +23,10 @@ typedef unsigned char byte;
typedef signed char sbyte;
typedef unsigned short word;
#ifndef CV_SMS
uintptr_t __at(0x6a) font_bitmap_a;
uintptr_t __at(0x6c) font_bitmap_0;
#endif
#define COLOR_FGBG(fg,bg) (((fg)<<4)|(bg))
#define COLOR_FG(fg) (((fg)<<4))

1
presets/sg1000 Symbolic link
View File

@ -0,0 +1 @@
coleco

199
src/platform/sg1000.ts Normal file
View File

@ -0,0 +1,199 @@
"use strict";
import { Platform, BaseMAMEPlatform, BaseZ80Platform, getToolForFilename_z80 } from "../baseplatform";
import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap } from "../emu";
import { hex, lzgmini, stringToByteArray } from "../util";
import { MasterAudio, SN76489_Audio } from "../audio";
import { TMS9918A } from "../video/tms9918a";
// http://www.smspower.org/Development/Index
// http://www.smspower.org/uploads/Development/sg1000.txt
var SG1000_PRESETS = [
{id:'stars.c', name:'Scrolling Starfield'},
{id:'cursorsmooth.c', name:'Moving Cursor'},
{id:'simplemusic.c', name:'Simple Music'},
{id:'musicplayer.c', name:'Multivoice Music'},
{id:'mode2bitmap.c', name:'Mode 2 Bitmap'},
{id:'mode2compressed.c', name:'Mode 2 Bitmap (LZG)'},
{id:'lines.c', name:'Mode 2 Lines'},
{id:'multicolor.c', name:'Multicolor Mode'},
];
var SG1000_KEYCODE_MAP = makeKeycodeMap([
[Keys.VK_UP, 0, 0x1],
[Keys.VK_DOWN, 0, 0x2],
[Keys.VK_LEFT, 0, 0x4],
[Keys.VK_RIGHT, 0, 0x8],
[Keys.VK_SPACE, 0, 0x10],
[Keys.VK_CONTROL, 0, 0x20],
[Keys.VK_R, 0, 0x40],
[Keys.VK_F, 0, 0x80],
[Keys.VK_D, 1, 0x1],
[Keys.VK_G, 1, 0x2],
[Keys.VK_A, 1, 0x4],
[Keys.VK_S, 1, 0x8],
[Keys.VK_1, 1, 0x10],
]);
/// standard emulator
const _SG1000Platform = function(mainElement) {
const cpuFrequency = 3579545; // MHz
const canvasWidth = 304;
const numTotalScanlines = 262;
const numVisibleScanlines = 240;
const cpuCyclesPerLine = Math.round(cpuFrequency / 60 / numTotalScanlines);
var cpu, ram, membus, iobus, rom;
var video, vdp, timer;
var audio, psg;
var inputs = new Uint8Array(4);
class SG1000Platform extends BaseZ80Platform implements Platform {
getPresets() { return SG1000_PRESETS; }
getToolForFilename = getToolForFilename_z80;
getDefaultExtension() { return ".c"; };
start() {
ram = new RAM(1024);
membus = {
read: newAddressDecoder([
[0xc000, 0xdfff, 0x3ff, function(a) { return ram.mem[a]; }],
[0x0000, 0xbfff, 0xffff, function(a) { return rom ? rom[a] : 0; }],
]),
write: newAddressDecoder([
[0xc000, 0xdfff, 0x3ff, function(a,v) { ram.mem[a] = v; }],
]),
isContended: function() { return false; },
};
iobus = {
read: function(addr) {
addr &= 0xff;
//console.log('IO read', hex(addr,4));
switch (addr) {
case 0xbe: return vdp.readData();
case 0xbf: return vdp.readStatus();
case 0xc0: case 0xdc: return inputs[0] ^ 0xff;
case 0xc1: case 0xdd: return inputs[1] ^ 0xff;
}
return 0;
},
write: function(addr, val) {
addr &= 0xff;
val &= 0xff;
//console.log('IO write', hex(addr,4), hex(val,2));
switch (addr) {
case 0xbe: return vdp.writeData(val);
case 0xbf: return vdp.writeAddress(val);
case 0x7e: case 0x7f: return psg.setData(val);
}
}
};
cpu = this.newCPU(membus, iobus);
video = new RasterVideo(mainElement,canvasWidth,numVisibleScanlines,{overscan:true});
video.create();
audio = new MasterAudio();
psg = new SN76489_Audio(audio);
var cru = {
setVDPInterrupt: (b) => {
if (b) {
cpu.nonMaskableInterrupt();
} else {
// TODO: reset interrupt?
}
}
};
vdp = new TMS9918A(video.canvas, cru, true); // true = 4 sprites/line
setKeyboardFromMap(video, inputs, SG1000_KEYCODE_MAP);
timer = new AnimationTimer(60, this.nextFrame.bind(this));
}
readAddress(addr) {
return membus.read(addr);
}
advance(novideo : boolean) {
for (var sl=0; sl<numTotalScanlines; sl++) {
this.runCPU(cpu, cpuCyclesPerLine);
if (sl < numVisibleScanlines)
vdp.drawScanline(sl);
}
vdp.updateCanvas();
}
loadROM(title, data) {
rom = padBytes(data, 0xc000);
this.reset();
}
loadState(state) {
cpu.loadState(state.c);
ram.mem.set(state.b);
vdp.restoreState(state.vdp);
inputs.set(state.in);
}
saveState() {
return {
c:this.getCPUState(),
b:ram.mem.slice(0),
vdp:vdp.getState(),
in:inputs.slice(0),
};
}
loadControlsState(state) {
inputs[0] = state.in0;
inputs[1] = state.in1;
inputs[2] = state.in2;
}
saveControlsState() {
return {
in0:inputs[0],
in1:inputs[1],
in2:inputs[2],
};
}
getCPUState() {
return cpu.saveState();
}
isRunning() {
return timer && timer.isRunning();
}
pause() {
timer.stop();
audio.stop();
}
resume() {
timer.start();
audio.start();
}
reset() {
cpu.reset();
cpu.setTstates(0);
vdp.reset();
psg.reset();
}
getDebugCategories() {
return super.getDebugCategories().concat(['VDP']);
}
getDebugInfo(category, state) {
switch (category) {
case 'VDP': return this.vdpStateToLongString(state.vdp);
default: return super.getDebugInfo(category, state);
}
}
vdpStateToLongString(ppu) {
return vdp.getRegsString();
}
}
return new SG1000Platform();
}
///
PLATFORMS['sg1000'] = _SG1000Platform;

View File

@ -0,0 +1,78 @@
XL2
H C areas D global symbols
M crt0
S _cv_spint_handler Ref0000
S l__DATA Ref0000
S _main Ref0000
S s__DATA Ref0000
S _cv_init Ref0000
S _cv_vint Ref0000
S .__.ABS. Def0000
S s__INITIALIZED Ref0000
S ___sdcc_call_hl Ref0000
S l__INITIALIZER Ref0000
S s__INITIALIZER Ref0000
A _CODE size 42 flags 0 addr 0
S _cv_start Def0000
A _HEADER size 0 flags 8 addr 0
A _HEADER0 size 2C flags 8 addr 8000
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 80
R 00 00 02 00
T 00 80 55 AA 00 00 00 00 00 00 00 00 00 00 C3
R 00 00 02 00 00 0C 00 00
T 0D 80 00 00 C3 00 00 C3 00 00 C3 00 00 C3 00 00
R 00 00 02 00
T 1B 80 C3 00 00 C3 21 00 C3 10 00 20 2F 20 2F 20
R 00 00 02 00 00 06 00 00 00 09 00 00
T 29 80 4E 4F 54
R 00 00 02 00
T 00 00
R 00 00 00 00
T 00 00 F3 31 00 74 ED 56 CD 00 00 CD 00 00 CD
R 00 00 00 00 00 09 05 00 02 0C 04 00
T 0D 00 00 00 C7
R 00 00 00 00 02 02 02 00
T 10 00
R 00 00 00 00
T 10 00 F5 C5 D5 E5 FD E5 CD 00 00 FD E1 E1 D1 C1
R 00 00 00 00 02 09 05 00
T 1E 00 F1 ED 45
R 00 00 00 00
T 21 00
R 00 00 00 00
T 21 00 E5 2A 00 00 7D B4 28 15 F5 C5 D5 FD E5 DB
R 00 00 00 00 02 04 00 00
T 2F 00 FC 4F DB FF 47 C5 CD 00 00 F1 FD E1 D1 C1
R 00 00 00 00 02 09 08 00
T 3D 00 F1
R 00 00 00 00
T 3E 00
R 00 00 00 00
T 3E 00 E1 FB ED 4D
R 00 00 00 00
T 00 00
R 00 00 05 00
T 00 00 01 00 00 78 B1 28 0F 21 00 00 36 00 0B 78
R 00 00 05 00 02 03 01 00 02 0A 03 00
T 0E 00 B1 28 05 5D 54 13 ED B0
R 00 00 05 00
T 16 00
R 00 00 05 00
T 16 00 01 00 00 78 B1 28 08 11 00 00 21 00 00 ED
R 00 00 05 00 02 03 09 00 02 0A 07 00 02 0D 0A 00
T 24 00 B0
R 00 00 05 00
T 25 00
R 00 00 05 00
T 00 00 C9
R 00 00 06 00

View File

@ -0,0 +1,61 @@
// (c) 2013 Philipp Klaus Krause
// This library 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 2.1 of the License, or (at your option) any later version.
// This library 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 library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef CV_H
#define CV_H 1
#include <stdint.h>
#define CV_LIBVERSION_MAJOR 0
#define CV_LIBVERSION_MINOR 24
#define CV_LIBVERSION_STRING "0.24"
#include "cv_input.h"
#include "cv_graphics.h"
#include "cv_sound.h"
// Set the handler for the vertical retrace interrupt.
extern void cv_set_vint_handler(void (* handler)(void));
// Get the handler for the vertical retrace interrupt.
extern void *cv_get_vint_handler(void);
// Get the vertical retrace frequency in Hz. 50 for PAL, 60 for NTSC.
unsigned char cv_get_vint_frequency(void);
#ifndef CV_SMS
enum cv_machine {
CV_COLECOVISION = 0, // Coleco ColecoVision
//CV_ADAM = 1, // Coleco Adam - TODO
//CV_SUPERGAME = 2, // Coleco ColecoVision with super game module
};
#else
enum cv_machine {
CV_SG1000 = 0, // Sega SG-1000
CV_SC3000 = 1, // Sega SC-3000
CV_MARKIII = 2, // Sega Mark III or Master System
//CV_GAMEGEAR = 3, // Sega Game Gear - TODO
};
#endif
// Find out on which machine we are running
enum cv_machine cv_get_machine(void);
// Get the contents of the refresh register R. Can be useful for seeding PRNGs.
uint8_t cv_get_r(void) __preserves_regs(b, c, d, e, h, iyl, iyh);
#endif

View File

@ -0,0 +1,250 @@
#ifndef CV_GRAPHICS_H
#define CV_GRAPHICS_H 1
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
/*
These are the functions for controlling the graphics chip.
While a function marked as not reentrant is called no other
such function from this file may be called at the same time.
*/
typedef uint16_t cv_vmemp; // 14-Bit video memory address type
#ifdef CV_SMS
typedef uint8_t cv_cmemp; // 5-bit color memory address type
#endif
/*
Activate / deactivate screen
This function is not reentrant!
*/
extern void cv_set_screen_active(bool status);
/*
Get screen status
*/
extern bool cv_get_screen_active(void);
/*
Enable / disable external video source.
This function is not reentrant!
*/
extern void cv_set_external_video(bool status);
/*
Get external video source enabled.
*/
extern bool cv_get_external_video(void);
// TMS99xxA and Sega Master System screen modes
enum cv_screenmode {
CV_SCREENMODE_STANDARD = 0x00, // Standard screen modes
CV_SCREENMODE_TEXT = 0x10,
CV_SCREENMODE_MULTICOLOR = 0x08,
CV_SCREENMODE_BITMAP = 0x02,
CV_SCREENMODE_BITMAP_TEXT = 0x12, // Usefull undocumented screen modes
CV_SCREENMODE_BITMAP_MULTICOLOR = 0x0a,
CV_SCREENMODE_TEXT_MULTICOLOR = 0x18, // Useless undocumented screen modes
CV_SCREENMODE_BITMAP_TEXT_MULTICOLOR = 0x1a,
CV_SCREENMODE_4 = 0x06, // Sega Master System 315-5124 mode
CV_SCREENMODE_4_224 = 0x16, // Sega Master System 315-5246 modes
CV_SCREENMODE_4_240 = 0x0e,
};
/*
Set screen mode.
This function is not reentrant!
*/
extern void cv_set_screen_mode(enum cv_screenmode mode);
/*
Get screen mode.
*/
extern enum cv_screenmode cv_get_screen_mode(void);
// TMS99xxA colors
enum cv_color {
CV_COLOR_TRANSPARENT = 0x0,
CV_COLOR_BLACK = 0x1,
CV_COLOR_GREEN = 0x2,
CV_COLOR_LIGHT_GREEN = 0x3,
CV_COLOR_BLUE = 0x4,
CV_COLOR_LIGHT_BLUE = 0x5,
CV_COLOR_DARK_RED = 0x6,
CV_COLOR_CYAN = 0x7,
CV_COLOR_RED = 0x8,
CV_COLOR_LIGHT_RED = 0x9,
CV_COLOR_YELLOW = 0xa,
CV_COLOR_LIGHT_YELLOW = 0xb,
CV_COLOR_DARK_GREEN = 0xc,
CV_COLOR_MAGENTA = 0xd,
CV_COLOR_GRAY = 0xe,
CV_COLOR_WHITE = 0xf
};
/*
Set colors. The foreground color is the text color in text mode,
in other modes it is unused.
The background color is used in all modes for the backdrop plane
(screen outside display area) and as the color that appears under
transparent characters. In text mode it is used for character
background. If the background color is the to cv_transparent,
the external video source is used as background image.
*/
extern void cv_set_colors(enum cv_color foreground, enum cv_color background);
/*
Set the location of the screen image table.
Must be a multiple of 0x400. Valid range: [0; 15360].
When the screenmode is CV_SCREENMODE4 on the Sega 315-5124,
the location is a multible of 0x800, and the bit 0x400 is and mask to the location.
This masking functionality is undocumented. To use only the documented
graphics chip functionality always set bit 0x400.
*/
extern void cv_set_image_table(cv_vmemp loc);
/*
Set the location of the color table. Must be a multiple of 0x40.
Valid range: [0; 16320].
When the screen mode ist CV_SCREENMODE_BITMAP,
CV_SCREENMODE_BITMAP_TEXT or CV_SCREENMODE_BITMAP_MULTICOLOR
this has a different meaning: The location of the color pattern table is
either 0 or 8192. The bits 4096 downto 128 are an and mask to the location.
This masking functionality is undocumented. To use only the documented
graphics chip functionality always set bits 4096 downto 128.
*/
void cv_set_color_table(cv_vmemp loc);
/*
Set the location of the character pattern table. Must be a multiple
of 0x800. Valid range: [0; 14336].
When the screen mode ist CV_SCREENMODE_BITMAP,
CV_SCREENMODE_BITMAP_TEXT or CV_SCREENMODE_BITMAP_MULTICOLOR
this has a different meaning: The location of the character pattern table is
either 0 or 8192. Unless you add 4096 to the location the first third of the table
is used for the last third of the screen. Unless you add 2048 to the location the
first third of the table is used for the middle part of the screen.
Thus the bits 4096 and 2048 are and and mask to the highest bits of the
address. This masking functionality is undocumented. To use only the
documented graphics chip functionality always set bits 4096 and 2048.
*/
// sdcc doesn't accept long function names.
extern void cv_set_character_pattern_t(cv_vmemp loc);
/*
Set the location of the sprite pattern table.
Must be a multiple of 0x800. Valid range: [0; 14336].
When the screenmode is CV_SCREENMODE4 the location is a multiple of 0x2000.
For the Sega 315-5124 and CV_SCREENMODE4, bits 0x800 and 0x1000 are
used as and mask. This masking functionality is undocumented. To use only the documented
graphics chip functionality always set bits 0x1000 downto 0x800.
*/
extern void cv_set_sprite_pattern_table(cv_vmemp loc);
/*
Set the location of the sprite attribute table.
Must be a multiple of 0x80. Valid range: [0; 16256].
*/
extern void cv_set_sprite_attribute_table(cv_vmemp loc);
/*
Set sprite size; When active, sprites are 16x16 pixels instead of 8x8.
This function is not reentrant!
*/
extern void cv_set_sprite_big(bool status);
/*
Get sprite size.
*/
extern bool cv_get_sprite_big(void);
/*
Set sprite magnification. When active, all sprites are displayed twice as big.
This function is not reentrant!
*/
extern void cv_set_sprite_magnification(bool status);
/*
Get sprite magnification.
*/
extern bool cv_get_sprite_magnification(void);
/*
Get sprite collission.
*/
extern bool cv_get_sprite_collission(void);
/*
Get invalid sprite. Returns true if there was an invalid sprite.
If sprite is not 0 it will point to the number of the invalid sprite.
*/
extern bool cv_get_sprite_invalid(uint8_t *sprite);
extern void cv_set_write_vram_address(cv_vmemp address) __preserves_regs(b, c, d, e);
extern void cv_set_read_vram_address(cv_vmemp address) __preserves_regs(b, c, d, e);
#ifdef CV_SMS
extern void cv_set_write_cram_address(cv_cmemp address) __preserves_regs(b, c, d, e);
#endif
extern void cv_memtovmemcpy_slow(const void *src, size_t n);
extern void cv_memtovmemcpy_fast(const void *src, size_t n);
extern void cv_vmemtomemcpy_slow(void *dest, size_t n);
extern void cv_vmemtomemcpy_fast(void *dest, size_t n);
extern void cv_vmemset_slow(int c, size_t n) __preserves_regs(iyl, iyh);
extern void cv_vmemset_fast(int c, size_t n) __preserves_regs(iyl, iyh);
static volatile __sfr __at 0xbe cv_graphics_port;
inline void cv_voutb(const uint8_t value)
{
__asm
cp a, (hl)
cp a, (hl)
nop
__endasm;
cv_graphics_port = value;
}
inline uint8_t cv_vinb(void)
{
__asm
cp a, (hl)
cp a, (hl)
nop
__endasm;
return(cv_graphics_port);
}
#ifdef CV_SMS
void cv_set_left_column_blank(bool status);
void cv_set_sprite_shift(bool status);
enum cv_scroll_inhibit {
CV_HORIZONTAL_SCROLL_INHIBIT = 0x40, // Do not scroll top 2 rows
CV_VERTICAL_SCROLL_INHIBIT = 0x80, // Do not scroll right 8 columns
};
void cv_set_scroll_inhibit(enum cv_scroll_inhibit inhibit);
void cv_set_hscroll(uint8_t offset);
void cv_set_vscroll(uint8_t offset);
#endif
#endif

View File

@ -0,0 +1,47 @@
#ifndef CV_INPUT_H
#define CV_INPUT_H 1
#include <stdint.h>
#ifndef CV_SMS
#define CV_FIRE_0 0x40
#define CV_FIRE_1 0x80
#define CV_FIRE_2 0x10
#define CV_FIRE_3 0x20
#define CV_LEFT 0x08
#define CV_DOWN 0x04
#define CV_RIGHT 0x02
#define CV_UP 0x01
#else
#define CV_UP 0x01
#define CV_DOWN 0x02
#define CV_LEFT 0x04
#define CV_RIGHT 0x08
#define CV_FIRE_0 0x10
#define CV_FIRE_1 0x20
#endif
struct cv_controller_state
{
uint8_t keypad; // Keypad: 0 - 9 as on keypad, * as 0xa, # as 0xb, 0xf for no key pressed or error.
uint8_t joystick;// Joystick: lowest 4 bit for joystick, higher 4 bit for fire buttons.
};
// Get keypad and joystick values.
void cv_get_controller_state(struct cv_controller_state *state, uint_fast8_t controller);
#define CV_SPIN_ACTIVE 0x10
#define CV_SPIN_RIGHT 0x20
// Set the handler for the spinner interrupt.
// This handler will be called when the wheel on the super action controller or the ball in the roller controller spin.
// The parameters passed to the handler correspond to the two super action controllers or
// the two axis in the roller controller. They can be anded with the above masks to test if they spinned, and which direction.
void cv_set_spint_handler(void (* handler)(uint_fast8_t, uint_fast8_t));
#endif

View File

@ -0,0 +1,37 @@
#ifndef CV_SOUND_H
#define CV_SOUND_H 1
#include <stdint.h>
#include <stdbool.h>
enum cv_soundchannel {
CV_SOUNDCHANNEL_0 = 0x0,
CV_SOUNDCHANNEL_1 = 0x2,
CV_SOUNDCHANNEL_2 = 0x4,
CV_SOUNDCHANNEL_NOISE = 0x6
};
enum cv_shift {
CV_NOISE_SHIFT_512 = 0,
CV_NOISE_SHIFT_1024 = 1,
CV_NOISE_SHIFT_2048 = 2,
CV_NOISE_SHIFT_CHAN2 = 3
};
/*
Set attenuation for given sound channel in dezibel. Maximum attenuation is 28 db,
granularity is 2 db.
*/
extern void cv_set_attenuation(enum cv_soundchannel channel, uint8_t dezibel);
/*
Set frequency of a tone generator. The frequency is 3.579/frequency_divider Mhz.
This function is not reentrant. While it is called neither cv_set_attenuation() nor
cv_set_noise() may be called. n should be a multiple of 32. The valid range is [0, 32736].
*/
extern void cv_set_frequency(enum cv_soundchannel channel, uint16_t frequency_divider);
extern void cv_set_noise(bool white, enum cv_shift shift);
#endif

View File

@ -0,0 +1,17 @@
#ifndef __CV_SUPPORT_H
#define __CV_SUPPORT_H 1
#include <stdint.h>
#include "cv_graphics.h"
extern void cv_init(void); // Initialize Colecovision library.
extern void cv_vdpout(const uint8_t reg, const uint8_t data) __preserves_regs(d, e, iyl, iyh); // Write data to VDP control register reg.
extern void cv_enable_nmi(void);
extern void cv_disable_nmi(void);
#endif

View File

@ -0,0 +1,32 @@
// (c) 2013 Philipp Klaus Krause
// This library 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 2.1 of the License, or (at your option) any later version.
// This library 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 library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef CVU_H
#define CVU_H 1
#define CVU_LIBVERSION_MAJOR 0
#define CVU_LIBVERSION_MINOR 17
#define CVU_LIBVERSION_STRING "0.17"
#include "cvu_input.h"
#include "cvu_graphics.h"
#include "cvu_sound.h"
#include "cvu_compression.h"
#include "cvu_f.h"
#include "cvu_c.h"
#endif

View File

@ -0,0 +1,37 @@
#ifndef CVU_C_H
#define CVU_C_H 1
#include "cvu_f.h"
// Complex fixed-point type
struct cvu_c
{
cvu_f r;
cvu_f i;
};
// Addition
//extern void cadd(struct c *l, const struct c *r);
#define cvu_cadd(x, y) {(x)->r += (y)->r; (x)->i += (y)->i;}
// Subtraction
//extern void csub(struct c *l, const struct c *r);
#define cvu_csub(x, y) {(x)->r -= (y)->r; (x)->i -= (y)->i;}
// Multiplication
extern void cvu_cmul(struct cvu_c *l, const struct cvu_c *r);
// Very inaccurate approximation
extern cvu_f cvu_cabs(const struct cvu_c *l);
// Dot product: Returns l.r^2 + l.i^2
extern cvu_f cvu_cdot(const struct cvu_c *l);
// Multiplication by fixed-point number.
extern void cvu_cfmul(struct cvu_c *l, cvu_f r);
// Convert from polar to coordinate representation
extern void cvu_c_from_polar(struct cvu_c *c, cvu_f phi, cvu_f d);
#endif

View File

@ -0,0 +1,93 @@
// These decompression routines are rather complicated to allow customization.
// If you only want to decompress some data into graphics memory, you can use
// the functions at the end of this file instead.
#ifndef CVU_COMPRESSION_H
#define CVU_COMPRESSION_H 1
#include <stdint.h>
#include "cvu_graphics.h"
// Huffman decompression
#undef CVU_HUFFMAN_ITERATIVE
#undef CVU_HUFFMAN_RECURSIVE
struct cvu_huffman_node // Changing this struct will affect asm implementation of cvu_get_huffman
{
uint8_t left; // Position of left node in tree or character.
uint8_t right; // Position of right node in tree or character.
};
struct cvu_huffman_state // Changing this struct will affect asm implementation of cvu_get_huffman, _read_from_array
{
uint8_t (*input)(void);
const struct cvu_huffman_node *nodes; // Array of nodes
uint8_t root; // Position of root node among nodes
uint8_t ls, bs, rs;
unsigned char bit; // Position of currently processed bit
uint8_t buffer; // Currently processed input byte
#ifdef CVU_HUFFMAN_RECURSIVE
uint8_t current; // Currently processed node
#endif
};
void cvu_init_huffman(struct cvu_huffman_state *restrict state, uint8_t (* input)(void), const struct cvu_huffman_node *restrict tree, uint8_t root, uint8_t ls, uint8_t bs, uint8_t rs);
uint8_t cvu_get_huffman(struct cvu_huffman_state *state);
// RLE decompression
struct cvu_rle_state // Changing this struct will affect asm implementation of cvu_get_rle, _read_from_array
{
uint8_t (*input)(void);
uint8_t escape;
uint8_t left;
uint8_t buffer;
};
void cvu_init_rle(struct cvu_rle_state *restrict state, uint8_t (* input)(void), uint8_t escape);
uint8_t cvu_get_rle(struct cvu_rle_state *state);
// LZK decompression
struct cvu_lzk_state
{
uint8_t (*input)(void);
uint8_t escape;
uint8_t left;
uint8_t offset;
uint8_t start;
uint8_t buffer[64];
};
void cvu_init_lzk(struct cvu_lzk_state *restrict state, uint8_t (* input)(void), uint8_t escape);
uint8_t cvu_get_lzk(struct cvu_lzk_state *state);
// Decompression routines which will handle all the details for you.
// Just create a cvu_compression_state struct, initialize it and decompress.
struct cvu_compression_state // Changing this struct will affect asm implementation of _read_from_array
{
struct cvu_huffman_state huffman;
struct cvu_rle_state rle;
const uint8_t *data;
};
// Initilization:
// data: compressed data
// state: compression struct to initialize
// tree: huffman tree generated by huffman_analyzer
// root, ls, bs, rs: constants generated by huffman_analyzer
// escape: constant generated by rle_analyzer
void cvu_init_compression(const uint8_t *restrict data, struct cvu_compression_state *restrict state, const struct cvu_huffman_node *restrict tree, uint8_t root, uint8_t ls, uint8_t bs, uint8_t rs, uint8_t escape);
// The functions below can be mixed:
// This function will return a decompressed octet on each invocation.
uint8_t cvu_get_compression(struct cvu_compression_state *state);
// This function will decompress and write n octets to graphics memory at dest.
// It is not reentrant and may not be called why any function from cvu_graphics.h marked as such is called.
void cvu_memtovmemcpy_compression(cv_vmemp dest, struct cvu_compression_state *state, size_t n);
// This function will decompress and write n octets to memory at dest.
void *cvu_memcpy_compression(void *restrict dest, struct cvu_compression_state *state, size_t n);
#endif

View File

@ -0,0 +1,46 @@
// Fixed-point math can be useful where e.g. smooth movement is desired, but
// using float would make the application too slow and big.
// cvu_f is a 10.6 fixed point type. 10.6 has been chosen to ensure that the
// type can represent coordinates on the ColecoVision screen and in some
// "buffer" space surrounding it (to allow calculation of e.g. reflection).
#ifndef CVU_F_H
#define CVU_F_H 1
#include <stdint.h>
#include <limits.h>
typedef int16_t cvu_f; // 10.6 fixed-point type.
#define CVU_F_R 6
#define CVU_F_PI 201
#define CVU_F_PI_2 100
#define CVU_F_SQRT2 90
#define CVU_F_SQRT1_2 45
#define CVU_F_MIN INT16_MIN
#define CVU_F_MAX INT16_MAX
// Convert integer to fixed-point
#define CVU_F2I(l) ((l) >> CVU_F_R)
// Convert fixed-point to integer
#define CVU_I2F(l) ((l) << CVU_F_R)
// Fixed-point multiplication
extern cvu_f cvu_fmul2(cvu_f l, cvu_f r);
// Fixed-point division
extern cvu_f cvu_fdiv2(cvu_f l, cvu_f r);
// Fixed-point sine
extern cvu_f cvu_fsin(cvu_f x);
// Fixed-point cosine
extern cvu_f cvu_fcos(cvu_f x);
// Fixed-point arcus tangens of x / y.
extern cvu_f cvu_fatan2(cvu_f y, cvu_f x);
#endif

View File

@ -0,0 +1,122 @@
#ifndef CVU_GRAPHICS_H
#define CVU_GRAPHICS_H 1
#include <stdint.h>
#include "cv_graphics.h"
#ifdef CV_SMS
/*
Copy n bytes of data from RAM at src to CRAM at dest.
This function is not reentrant!
The speed of this function depends on the active video mode
and if the screen is active.
*/
extern void cvu_memtocmemcpy(cv_cmemp dest, const void * src, size_t n);
#endif
/*
Copy n bytes of data from RAM at src to VRAM at dest.
This function is not reentrant!
The speed of this function depends on the active video mode
and if the screen is active.
*/
extern void cvu_memtovmemcpy(cv_vmemp dest, const void * src, size_t n);
/*
Copy n bytes of data from VRAM at src to RAM at dest.
This function is not reentrant!
The speed of this function depends on the active video mode
and if the screen is active.
*/
extern void cvu_vmemtomemcpy(void *dest, cv_vmemp src, size_t n);
/*
Set n bytes of VRAM at dest to c.
This function is not reentrant!
The speed of this function depends on the active video mode
and if the screen is active.
*/
extern void cvu_vmemset(cv_vmemp dest, int c, size_t n);
/*
Write an octet to graphics memory at dest.
This function is not reentrant!
*/
extern void cvu_voutb(const uint8_t value, const cv_vmemp dest);
/*
Read an octet from graphics memory at src.
This function is not reentrant!
*/
extern uint8_t cvu_vinb(const cv_vmemp src);
struct cvu_sprite
{
uint8_t y;
uint8_t x;
uint8_t name;
uint8_t tag;
};
#ifdef CV_SMS
struct cvu_sprite4
{
uint8_t y;
uint8_t x;
uint8_t name;
};
#endif
// Write sprite to display memory. Use the location of the sprite table as base. number should be in [0, 31].
inline void cvu_set_sprite(const cv_vmemp base, uint_fast8_t number, const struct cvu_sprite *sprite)
{
cv_set_write_vram_address((base) + (number) * 0x4);
cv_memtovmemcpy_slow((sprite), 4);
}
// Write sprite to display memory (in mode 4). Use the location of the sprite table as base. number should be in [0, 63].
#ifdef CV_SMS
inline void cvu_set_sprite4(const cv_vmemp base, uint_fast8_t number, const struct cvu_sprite4 *sprite)
{
cvu_voutb(sprite->y, base + number);
cv_set_write_vram_address(base + 0x80 + number * 2);
cv_voutb(sprite->x);
cv_voutb(sprite->name);
}
#endif
// Todo: is cvu_get_sprite needed?
// Set the x coordinate of the sprite's upper left corner. x will be clamped to [-32, 255]
extern void cvu_set_sprite_x(struct cvu_sprite *sprite, int x) __preserves_regs(d, e);
extern int cvu_get_sprite_x(const struct cvu_sprite *sprite) __preserves_regs(b, c, d, e);
// Set the y coordinate of the sprite's upper left corner. y will be clamped to [-32, 207]
extern void cvu_set_sprite_y(struct cvu_sprite *sprite, int y) __preserves_regs(d, e);
extern int cvu_get_sprite_y(const struct cvu_sprite *sprite) __preserves_regs(d, e);
// Set them both at once.
extern void cvu_set_sprite_xy(struct cvu_sprite *sprite, int x, int y);
// Set the sprite's color.
inline void cvu_set_sprite_color(struct cvu_sprite *sprite, enum cv_color color)
{
sprite->tag = (sprite->tag & 0x80) | color;
}
extern enum cv_color cvu_get_sprite_color(struct cvu_sprite *sprite);
#endif

View File

@ -0,0 +1,15 @@
#ifndef CVU_INPUT_H
#define CVU_INPUT_H 1
#include <stdint.h>
#include "cv_input.h"
// For the super action controllers this gives the spinner movement (total relative movement since last call, negative for left, positive for right)
// For the roller controller this gives the ball movement (total relative as above).
// Using this function will set a libvu-specific spint handler, so it is incompatible with using a custom spint handler.
int_fast8_t cvu_get_spinner(uint_fast8_t controller);
#endif

View File

@ -0,0 +1,45 @@
#ifndef CVU_SOUND_H
#define CVU_SOUND 1
#include <stdint.h>
#include "cv_sound.h"
extern const uint16_t CVU_TUNING_ISO16_EQUAL[15]; // ISO 16 pitch (A at 440 Hz) with equal tuning.
extern const uint16_t CVU_TUNING_SCIENTIFIC_EQUAL[15]; // Scientific pitch (C at 256 Hz) with equal tuning.
extern const uint8_t CVU_VOLUME_DEFAULT[4];
extern const uint16_t CVU_EMPTY_MUSIC;
// channel holds the channel that will be used to play the music.
// volume is a pointer to an array of loudnesses in Dezibel for p, mp, mf, f.
// tuning is a pointer to an arrays of frequency dividers for the halftones of oktave 0.
// sixteenth_notes_per_second should explain itself.
// notes is a pointer to the music in the following format:
// Every note cosists of 16 bits. The most significant four mark the octave, the next 4
// the halftone (0xf means pause) the next 4 bits give the absolute length. The next 2
// give the relative length. the last 2 bits are the loudness.
// The rest of the structure's members are for internal use by cvu_play_music().
struct cvu_music
{
enum cv_soundchannel channel;
const uint8_t *volume;
const uint16_t *tuning;
uint8_t sixteenth_notes_per_second;
const uint16_t *notes;
uint16_t note_ticks_remaining;
uint16_t pause_ticks_remaining;
};
// This will initialize a cvu_music structure with default values for all
// members except notes.
extern void cvu_init_music(struct cvu_music *music);
// This function should be placed inside the vint handler or triggered by the vint handler.
// It will return false once it is finished playing the music.
extern bool cvu_play_music(struct cvu_music *restrict music);
#endif

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,126 @@
1 ; crt0.s for Colecovision cart
2
3 .module crt0
4 .globl _main
5 .globl _cv_init
6 .globl _cv_spint_handler
7 .globl _cv_vint
8 .globl _cv_start
9 .globl ___sdcc_call_hl
10
11 .area _HEADER(ABS)
0000 12 .org 0x0000
13
0000 C3r00r00 [10] 14 jp _cv_start
15
0038 16 .org 0x0038
0038 C3r10r00 [10] 17 jp vint
18
0066 19 .org 0x0066
0066 C3r22r00 [10] 20 jp pint
21
22 ; Ordering of segments for the linker - copied from sdcc crt0.s
23 .area _CODE
24 .area _INITIALIZER
25 .area _HOME
26 .area _GSINIT
27 .area _GSFINAL
28 .area _DATA
29 .area _INITIALIZED
30 .area _BSEG
31 .area _BSS
32 .area _HEAP
33
34 .area _CODE
35
0000 36 _cv_start:
0000 F3 [ 4] 37 di
0001 31 00 E0 [10] 38 ld sp, #0xe000 ; Set stack pointer directly above top of memory.
0004 ED 56 [ 8] 39 im 1
40
0006 CDr00r00 [17] 41 call gsinit ; Initialize global and static variables.
42
0009 CDr00r00 [17] 43 call _cv_init ; Initialize Colecovision specific stuff.
000C CDr00r00 [17] 44 call _main
000F C7 [11] 45 rst 0x0 ; Restart when main() returns.
46
0010 47 vint:
0010 F5 [11] 48 push af
0011 C5 [11] 49 push bc
0012 D5 [11] 50 push de
0013 E5 [11] 51 push hl
0014 FD E5 [15] 52 push iy
0016 CDr00r00 [17] 53 call _cv_vint
0019 FD E1 [14] 54 pop iy
001B E1 [10] 55 pop hl
001C D1 [10] 56 pop de
001D C1 [10] 57 pop bc
001E F1 [10] 58 pop af
001F FB [ 4] 59 ei
0020 ED 4D [14] 60 reti
61
0022 62 pint:
0022 F5 [11] 63 push af
0023 C5 [11] 64 push bc
0024 D5 [11] 65 push de
0025 E5 [11] 66 push hl
0026 FD E5 [15] 67 push iy
68
0028 FD E1 [14] 69 pop iy
002A E1 [10] 70 pop hl
002B D1 [10] 71 pop de
002C C1 [10] 72 pop bc
002D F1 [10] 73 pop af
002E ED 45 [14] 74 retn
75
76 .area _GSINIT
0000 77 gsinit::
78
79 ; Delay for Mark III
0000 16 04 [ 7] 80 ld d, #0x04
0002 81 label0:
0002 1E FF [ 7] 82 ld e, #0xff
0004 83 label1:
0004 3E FF [ 7] 84 ld a, #0xff
0006 85 label2:
0006 3D [ 4] 86 dec a
0007 C2r06r00 [10] 87 jp NZ, label2
000A 1D [ 4] 88 dec e
000B C2r04r00 [10] 89 jp NZ, label1
000E 15 [ 4] 90 dec d
000F C2r02r00 [10] 91 jp NZ, label0
92
93 ; Implicitly zeroed global and static variables.
0012 01r00r00 [10] 94 ld bc, #l__DATA
0015 78 [ 4] 95 ld a, b
0016 B1 [ 4] 96 or a, c
0017 28 0F [12] 97 jr Z, zeroed_data
0019 21r00r00 [10] 98 ld hl, #s__DATA
001C 36 00 [10] 99 ld (hl), #0x00
001E 0B [ 6] 100 dec bc
001F 78 [ 4] 101 ld a, b
0020 B1 [ 4] 102 or a, c
0021 28 05 [12] 103 jr Z, zeroed_data
0023 5D [ 4] 104 ld e, l
0024 54 [ 4] 105 ld d, h
0025 13 [ 6] 106 inc de
0026 ED B0 [21] 107 ldir
0028 108 zeroed_data:
109
110 ; Explicitly initialized global variables.
0028 01r00r00 [10] 111 ld bc, #l__INITIALIZER
002B 78 [ 4] 112 ld a, b
002C B1 [ 4] 113 or a, c
002D 28 08 [12] 114 jr Z, gsinit_static
002F 11r00r00 [10] 115 ld de, #s__INITIALIZED
0032 21r00r00 [10] 116 ld hl, #s__INITIALIZER
0035 ED B0 [21] 117 ldir
118
0037 119 gsinit_static:
120 ; Explicitly initialized static variables inserted by compiler here.
121
122 .area _GSFINAL
0000 C9 [10] 123 ret
124
125 .area _HOME
126

View File

@ -0,0 +1,88 @@
XL2
H E areas D global symbols
M crt0
S _cv_spint_handler Ref0000
S l__DATA Ref0000
S _main Ref0000
S s__DATA Ref0000
S _cv_init Ref0000
S _cv_vint Ref0000
S .__.ABS. Def0000
S s__INITIALIZED Ref0000
S ___sdcc_call_hl Ref0000
S l__INITIALIZER Ref0000
S s__INITIALIZER Ref0000
A _CODE size 30 flags 0 addr 0
S _cv_start Def0000
A _HEADER size 0 flags 8 addr 0
A _HEADER0 size 3 flags 8 addr 0
A _HEADER1 size 3 flags 8 addr 38
A _HEADER2 size 3 flags 8 addr 66
A _INITIALIZER size 0 flags 0 addr 0
A _HOME size 0 flags 0 addr 0
A _GSINIT size 37 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 02 00
T 00 00 C3 00 00
R 00 00 02 00 00 03 00 00
T 38 00
R 00 00 03 00
T 38 00 C3 10 00
R 00 00 03 00 00 03 00 00
T 66 00
R 00 00 04 00
T 66 00 C3 22 00
R 00 00 04 00 00 03 00 00
T 00 00
R 00 00 00 00
T 00 00 F3 31 00 E0 ED 56 CD 00 00 CD 00 00 CD
R 00 00 00 00 00 09 07 00 02 0C 04 00
T 0D 00 00 00 C7
R 00 00 00 00 02 02 02 00
T 10 00
R 00 00 00 00
T 10 00 F5 C5 D5 E5 FD E5 CD 00 00 FD E1 E1 D1 C1
R 00 00 00 00 02 09 05 00
T 1E 00 F1 FB ED 4D
R 00 00 00 00
T 22 00
R 00 00 00 00
T 22 00 F5 C5 D5 E5 FD E5 FD E1 E1 D1 C1 F1 ED 45
R 00 00 00 00
T 00 00
R 00 00 07 00
T 00 00 16 04
R 00 00 07 00
T 02 00
R 00 00 07 00
T 02 00 1E FF
R 00 00 07 00
T 04 00
R 00 00 07 00
T 04 00 3E FF
R 00 00 07 00
T 06 00
R 00 00 07 00
T 06 00 3D C2 06 00 1D C2 04 00 15 C2 02 00 01
R 00 00 07 00 00 04 07 00 00 08 07 00 00 0C 07 00
T 13 00 00 00 78 B1 28 0F 21 00 00 36 00 0B 78 B1
R 00 00 07 00 02 02 01 00 02 09 03 00
T 21 00 28 05 5D 54 13 ED B0
R 00 00 07 00
T 28 00
R 00 00 07 00
T 28 00 01 00 00 78 B1 28 08 11 00 00 21 00 00 ED
R 00 00 07 00 02 03 09 00 02 0A 07 00 02 0D 0A 00
T 36 00 B0
R 00 00 07 00
T 37 00
R 00 00 07 00
T 00 00 C9
R 00 00 08 00

View File

@ -0,0 +1,61 @@
// (c) 2013 Philipp Klaus Krause
// This library 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 2.1 of the License, or (at your option) any later version.
// This library 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 library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef CV_H
#define CV_H 1
#include <stdint.h>
#define CV_LIBVERSION_MAJOR 0
#define CV_LIBVERSION_MINOR 24
#define CV_LIBVERSION_STRING "0.24"
#include "cv_input.h"
#include "cv_graphics.h"
#include "cv_sound.h"
// Set the handler for the vertical retrace interrupt.
extern void cv_set_vint_handler(void (* handler)(void));
// Get the handler for the vertical retrace interrupt.
extern void *cv_get_vint_handler(void);
// Get the vertical retrace frequency in Hz. 50 for PAL, 60 for NTSC.
unsigned char cv_get_vint_frequency(void);
#ifndef CV_SMS
enum cv_machine {
CV_COLECOVISION = 0, // Coleco ColecoVision
//CV_ADAM = 1, // Coleco Adam - TODO
//CV_SUPERGAME = 2, // Coleco ColecoVision with super game module
};
#else
enum cv_machine {
CV_SG1000 = 0, // Sega SG-1000
CV_SC3000 = 1, // Sega SC-3000
CV_MARKIII = 2, // Sega Mark III or Master System
//CV_GAMEGEAR = 3, // Sega Game Gear - TODO
};
#endif
// Find out on which machine we are running
enum cv_machine cv_get_machine(void);
// Get the contents of the refresh register R. Can be useful for seeding PRNGs.
uint8_t cv_get_r(void) __preserves_regs(b, c, d, e, h, iyl, iyh);
#endif

View File

@ -0,0 +1,250 @@
#ifndef CV_GRAPHICS_H
#define CV_GRAPHICS_H 1
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
/*
These are the functions for controlling the graphics chip.
While a function marked as not reentrant is called no other
such function from this file may be called at the same time.
*/
typedef uint16_t cv_vmemp; // 14-Bit video memory address type
#ifdef CV_SMS
typedef uint8_t cv_cmemp; // 5-bit color memory address type
#endif
/*
Activate / deactivate screen
This function is not reentrant!
*/
extern void cv_set_screen_active(bool status);
/*
Get screen status
*/
extern bool cv_get_screen_active(void);
/*
Enable / disable external video source.
This function is not reentrant!
*/
extern void cv_set_external_video(bool status);
/*
Get external video source enabled.
*/
extern bool cv_get_external_video(void);
// TMS99xxA and Sega Master System screen modes
enum cv_screenmode {
CV_SCREENMODE_STANDARD = 0x00, // Standard screen modes
CV_SCREENMODE_TEXT = 0x10,
CV_SCREENMODE_MULTICOLOR = 0x08,
CV_SCREENMODE_BITMAP = 0x02,
CV_SCREENMODE_BITMAP_TEXT = 0x12, // Usefull undocumented screen modes
CV_SCREENMODE_BITMAP_MULTICOLOR = 0x0a,
CV_SCREENMODE_TEXT_MULTICOLOR = 0x18, // Useless undocumented screen modes
CV_SCREENMODE_BITMAP_TEXT_MULTICOLOR = 0x1a,
CV_SCREENMODE_4 = 0x06, // Sega Master System 315-5124 mode
CV_SCREENMODE_4_224 = 0x16, // Sega Master System 315-5246 modes
CV_SCREENMODE_4_240 = 0x0e,
};
/*
Set screen mode.
This function is not reentrant!
*/
extern void cv_set_screen_mode(enum cv_screenmode mode);
/*
Get screen mode.
*/
extern enum cv_screenmode cv_get_screen_mode(void);
// TMS99xxA colors
enum cv_color {
CV_COLOR_TRANSPARENT = 0x0,
CV_COLOR_BLACK = 0x1,
CV_COLOR_GREEN = 0x2,
CV_COLOR_LIGHT_GREEN = 0x3,
CV_COLOR_BLUE = 0x4,
CV_COLOR_LIGHT_BLUE = 0x5,
CV_COLOR_DARK_RED = 0x6,
CV_COLOR_CYAN = 0x7,
CV_COLOR_RED = 0x8,
CV_COLOR_LIGHT_RED = 0x9,
CV_COLOR_YELLOW = 0xa,
CV_COLOR_LIGHT_YELLOW = 0xb,
CV_COLOR_DARK_GREEN = 0xc,
CV_COLOR_MAGENTA = 0xd,
CV_COLOR_GRAY = 0xe,
CV_COLOR_WHITE = 0xf
};
/*
Set colors. The foreground color is the text color in text mode,
in other modes it is unused.
The background color is used in all modes for the backdrop plane
(screen outside display area) and as the color that appears under
transparent characters. In text mode it is used for character
background. If the background color is the to cv_transparent,
the external video source is used as background image.
*/
extern void cv_set_colors(enum cv_color foreground, enum cv_color background);
/*
Set the location of the screen image table.
Must be a multiple of 0x400. Valid range: [0; 15360].
When the screenmode is CV_SCREENMODE4 on the Sega 315-5124,
the location is a multible of 0x800, and the bit 0x400 is and mask to the location.
This masking functionality is undocumented. To use only the documented
graphics chip functionality always set bit 0x400.
*/
extern void cv_set_image_table(cv_vmemp loc);
/*
Set the location of the color table. Must be a multiple of 0x40.
Valid range: [0; 16320].
When the screen mode ist CV_SCREENMODE_BITMAP,
CV_SCREENMODE_BITMAP_TEXT or CV_SCREENMODE_BITMAP_MULTICOLOR
this has a different meaning: The location of the color pattern table is
either 0 or 8192. The bits 4096 downto 128 are an and mask to the location.
This masking functionality is undocumented. To use only the documented
graphics chip functionality always set bits 4096 downto 128.
*/
void cv_set_color_table(cv_vmemp loc);
/*
Set the location of the character pattern table. Must be a multiple
of 0x800. Valid range: [0; 14336].
When the screen mode ist CV_SCREENMODE_BITMAP,
CV_SCREENMODE_BITMAP_TEXT or CV_SCREENMODE_BITMAP_MULTICOLOR
this has a different meaning: The location of the character pattern table is
either 0 or 8192. Unless you add 4096 to the location the first third of the table
is used for the last third of the screen. Unless you add 2048 to the location the
first third of the table is used for the middle part of the screen.
Thus the bits 4096 and 2048 are and and mask to the highest bits of the
address. This masking functionality is undocumented. To use only the
documented graphics chip functionality always set bits 4096 and 2048.
*/
// sdcc doesn't accept long function names.
extern void cv_set_character_pattern_t(cv_vmemp loc);
/*
Set the location of the sprite pattern table.
Must be a multiple of 0x800. Valid range: [0; 14336].
When the screenmode is CV_SCREENMODE4 the location is a multiple of 0x2000.
For the Sega 315-5124 and CV_SCREENMODE4, bits 0x800 and 0x1000 are
used as and mask. This masking functionality is undocumented. To use only the documented
graphics chip functionality always set bits 0x1000 downto 0x800.
*/
extern void cv_set_sprite_pattern_table(cv_vmemp loc);
/*
Set the location of the sprite attribute table.
Must be a multiple of 0x80. Valid range: [0; 16256].
*/
extern void cv_set_sprite_attribute_table(cv_vmemp loc);
/*
Set sprite size; When active, sprites are 16x16 pixels instead of 8x8.
This function is not reentrant!
*/
extern void cv_set_sprite_big(bool status);
/*
Get sprite size.
*/
extern bool cv_get_sprite_big(void);
/*
Set sprite magnification. When active, all sprites are displayed twice as big.
This function is not reentrant!
*/
extern void cv_set_sprite_magnification(bool status);
/*
Get sprite magnification.
*/
extern bool cv_get_sprite_magnification(void);
/*
Get sprite collission.
*/
extern bool cv_get_sprite_collission(void);
/*
Get invalid sprite. Returns true if there was an invalid sprite.
If sprite is not 0 it will point to the number of the invalid sprite.
*/
extern bool cv_get_sprite_invalid(uint8_t *sprite);
extern void cv_set_write_vram_address(cv_vmemp address) __preserves_regs(b, c, d, e);
extern void cv_set_read_vram_address(cv_vmemp address) __preserves_regs(b, c, d, e);
#ifdef CV_SMS
extern void cv_set_write_cram_address(cv_cmemp address) __preserves_regs(b, c, d, e);
#endif
extern void cv_memtovmemcpy_slow(const void *src, size_t n);
extern void cv_memtovmemcpy_fast(const void *src, size_t n);
extern void cv_vmemtomemcpy_slow(void *dest, size_t n);
extern void cv_vmemtomemcpy_fast(void *dest, size_t n);
extern void cv_vmemset_slow(int c, size_t n) __preserves_regs(iyl, iyh);
extern void cv_vmemset_fast(int c, size_t n) __preserves_regs(iyl, iyh);
static volatile __sfr __at 0xbe cv_graphics_port;
inline void cv_voutb(const uint8_t value)
{
__asm
cp a, (hl)
cp a, (hl)
nop
__endasm;
cv_graphics_port = value;
}
inline uint8_t cv_vinb(void)
{
__asm
cp a, (hl)
cp a, (hl)
nop
__endasm;
return(cv_graphics_port);
}
#ifdef CV_SMS
void cv_set_left_column_blank(bool status);
void cv_set_sprite_shift(bool status);
enum cv_scroll_inhibit {
CV_HORIZONTAL_SCROLL_INHIBIT = 0x40, // Do not scroll top 2 rows
CV_VERTICAL_SCROLL_INHIBIT = 0x80, // Do not scroll right 8 columns
};
void cv_set_scroll_inhibit(enum cv_scroll_inhibit inhibit);
void cv_set_hscroll(uint8_t offset);
void cv_set_vscroll(uint8_t offset);
#endif
#endif

View File

@ -0,0 +1,47 @@
#ifndef CV_INPUT_H
#define CV_INPUT_H 1
#include <stdint.h>
#ifndef CV_SMS
#define CV_FIRE_0 0x40
#define CV_FIRE_1 0x80
#define CV_FIRE_2 0x10
#define CV_FIRE_3 0x20
#define CV_LEFT 0x08
#define CV_DOWN 0x04
#define CV_RIGHT 0x02
#define CV_UP 0x01
#else
#define CV_UP 0x01
#define CV_DOWN 0x02
#define CV_LEFT 0x04
#define CV_RIGHT 0x08
#define CV_FIRE_0 0x10
#define CV_FIRE_1 0x20
#endif
struct cv_controller_state
{
uint8_t keypad; // Keypad: 0 - 9 as on keypad, * as 0xa, # as 0xb, 0xf for no key pressed or error.
uint8_t joystick;// Joystick: lowest 4 bit for joystick, higher 4 bit for fire buttons.
};
// Get keypad and joystick values.
void cv_get_controller_state(struct cv_controller_state *state, uint_fast8_t controller);
#define CV_SPIN_ACTIVE 0x10
#define CV_SPIN_RIGHT 0x20
// Set the handler for the spinner interrupt.
// This handler will be called when the wheel on the super action controller or the ball in the roller controller spin.
// The parameters passed to the handler correspond to the two super action controllers or
// the two axis in the roller controller. They can be anded with the above masks to test if they spinned, and which direction.
void cv_set_spint_handler(void (* handler)(uint_fast8_t, uint_fast8_t));
#endif

View File

@ -0,0 +1,37 @@
#ifndef CV_SOUND_H
#define CV_SOUND_H 1
#include <stdint.h>
#include <stdbool.h>
enum cv_soundchannel {
CV_SOUNDCHANNEL_0 = 0x0,
CV_SOUNDCHANNEL_1 = 0x2,
CV_SOUNDCHANNEL_2 = 0x4,
CV_SOUNDCHANNEL_NOISE = 0x6
};
enum cv_shift {
CV_NOISE_SHIFT_512 = 0,
CV_NOISE_SHIFT_1024 = 1,
CV_NOISE_SHIFT_2048 = 2,
CV_NOISE_SHIFT_CHAN2 = 3
};
/*
Set attenuation for given sound channel in dezibel. Maximum attenuation is 28 db,
granularity is 2 db.
*/
extern void cv_set_attenuation(enum cv_soundchannel channel, uint8_t dezibel);
/*
Set frequency of a tone generator. The frequency is 3.579/frequency_divider Mhz.
This function is not reentrant. While it is called neither cv_set_attenuation() nor
cv_set_noise() may be called. n should be a multiple of 32. The valid range is [0, 32736].
*/
extern void cv_set_frequency(enum cv_soundchannel channel, uint16_t frequency_divider);
extern void cv_set_noise(bool white, enum cv_shift shift);
#endif

View File

@ -0,0 +1,17 @@
#ifndef __CV_SUPPORT_H
#define __CV_SUPPORT_H 1
#include <stdint.h>
#include "cv_graphics.h"
extern void cv_init(void); // Initialize Colecovision library.
extern void cv_vdpout(const uint8_t reg, const uint8_t data) __preserves_regs(d, e, iyl, iyh); // Write data to VDP control register reg.
extern void cv_enable_nmi(void);
extern void cv_disable_nmi(void);
#endif

View File

@ -0,0 +1,32 @@
// (c) 2013 Philipp Klaus Krause
// This library 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 2.1 of the License, or (at your option) any later version.
// This library 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 library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef CVU_H
#define CVU_H 1
#define CVU_LIBVERSION_MAJOR 0
#define CVU_LIBVERSION_MINOR 17
#define CVU_LIBVERSION_STRING "0.17"
#include "cvu_input.h"
#include "cvu_graphics.h"
#include "cvu_sound.h"
#include "cvu_compression.h"
#include "cvu_f.h"
#include "cvu_c.h"
#endif

View File

@ -0,0 +1,37 @@
#ifndef CVU_C_H
#define CVU_C_H 1
#include "cvu_f.h"
// Complex fixed-point type
struct cvu_c
{
cvu_f r;
cvu_f i;
};
// Addition
//extern void cadd(struct c *l, const struct c *r);
#define cvu_cadd(x, y) {(x)->r += (y)->r; (x)->i += (y)->i;}
// Subtraction
//extern void csub(struct c *l, const struct c *r);
#define cvu_csub(x, y) {(x)->r -= (y)->r; (x)->i -= (y)->i;}
// Multiplication
extern void cvu_cmul(struct cvu_c *l, const struct cvu_c *r);
// Very inaccurate approximation
extern cvu_f cvu_cabs(const struct cvu_c *l);
// Dot product: Returns l.r^2 + l.i^2
extern cvu_f cvu_cdot(const struct cvu_c *l);
// Multiplication by fixed-point number.
extern void cvu_cfmul(struct cvu_c *l, cvu_f r);
// Convert from polar to coordinate representation
extern void cvu_c_from_polar(struct cvu_c *c, cvu_f phi, cvu_f d);
#endif

View File

@ -0,0 +1,93 @@
// These decompression routines are rather complicated to allow customization.
// If you only want to decompress some data into graphics memory, you can use
// the functions at the end of this file instead.
#ifndef CVU_COMPRESSION_H
#define CVU_COMPRESSION_H 1
#include <stdint.h>
#include "cvu_graphics.h"
// Huffman decompression
#undef CVU_HUFFMAN_ITERATIVE
#undef CVU_HUFFMAN_RECURSIVE
struct cvu_huffman_node // Changing this struct will affect asm implementation of cvu_get_huffman
{
uint8_t left; // Position of left node in tree or character.
uint8_t right; // Position of right node in tree or character.
};
struct cvu_huffman_state // Changing this struct will affect asm implementation of cvu_get_huffman, _read_from_array
{
uint8_t (*input)(void);
const struct cvu_huffman_node *nodes; // Array of nodes
uint8_t root; // Position of root node among nodes
uint8_t ls, bs, rs;
unsigned char bit; // Position of currently processed bit
uint8_t buffer; // Currently processed input byte
#ifdef CVU_HUFFMAN_RECURSIVE
uint8_t current; // Currently processed node
#endif
};
void cvu_init_huffman(struct cvu_huffman_state *restrict state, uint8_t (* input)(void), const struct cvu_huffman_node *restrict tree, uint8_t root, uint8_t ls, uint8_t bs, uint8_t rs);
uint8_t cvu_get_huffman(struct cvu_huffman_state *state);
// RLE decompression
struct cvu_rle_state // Changing this struct will affect asm implementation of cvu_get_rle, _read_from_array
{
uint8_t (*input)(void);
uint8_t escape;
uint8_t left;
uint8_t buffer;
};
void cvu_init_rle(struct cvu_rle_state *restrict state, uint8_t (* input)(void), uint8_t escape);
uint8_t cvu_get_rle(struct cvu_rle_state *state);
// LZK decompression
struct cvu_lzk_state
{
uint8_t (*input)(void);
uint8_t escape;
uint8_t left;
uint8_t offset;
uint8_t start;
uint8_t buffer[64];
};
void cvu_init_lzk(struct cvu_lzk_state *restrict state, uint8_t (* input)(void), uint8_t escape);
uint8_t cvu_get_lzk(struct cvu_lzk_state *state);
// Decompression routines which will handle all the details for you.
// Just create a cvu_compression_state struct, initialize it and decompress.
struct cvu_compression_state // Changing this struct will affect asm implementation of _read_from_array
{
struct cvu_huffman_state huffman;
struct cvu_rle_state rle;
const uint8_t *data;
};
// Initilization:
// data: compressed data
// state: compression struct to initialize
// tree: huffman tree generated by huffman_analyzer
// root, ls, bs, rs: constants generated by huffman_analyzer
// escape: constant generated by rle_analyzer
void cvu_init_compression(const uint8_t *restrict data, struct cvu_compression_state *restrict state, const struct cvu_huffman_node *restrict tree, uint8_t root, uint8_t ls, uint8_t bs, uint8_t rs, uint8_t escape);
// The functions below can be mixed:
// This function will return a decompressed octet on each invocation.
uint8_t cvu_get_compression(struct cvu_compression_state *state);
// This function will decompress and write n octets to graphics memory at dest.
// It is not reentrant and may not be called why any function from cvu_graphics.h marked as such is called.
void cvu_memtovmemcpy_compression(cv_vmemp dest, struct cvu_compression_state *state, size_t n);
// This function will decompress and write n octets to memory at dest.
void *cvu_memcpy_compression(void *restrict dest, struct cvu_compression_state *state, size_t n);
#endif

View File

@ -0,0 +1,46 @@
// Fixed-point math can be useful where e.g. smooth movement is desired, but
// using float would make the application too slow and big.
// cvu_f is a 10.6 fixed point type. 10.6 has been chosen to ensure that the
// type can represent coordinates on the ColecoVision screen and in some
// "buffer" space surrounding it (to allow calculation of e.g. reflection).
#ifndef CVU_F_H
#define CVU_F_H 1
#include <stdint.h>
#include <limits.h>
typedef int16_t cvu_f; // 10.6 fixed-point type.
#define CVU_F_R 6
#define CVU_F_PI 201
#define CVU_F_PI_2 100
#define CVU_F_SQRT2 90
#define CVU_F_SQRT1_2 45
#define CVU_F_MIN INT16_MIN
#define CVU_F_MAX INT16_MAX
// Convert integer to fixed-point
#define CVU_F2I(l) ((l) >> CVU_F_R)
// Convert fixed-point to integer
#define CVU_I2F(l) ((l) << CVU_F_R)
// Fixed-point multiplication
extern cvu_f cvu_fmul2(cvu_f l, cvu_f r);
// Fixed-point division
extern cvu_f cvu_fdiv2(cvu_f l, cvu_f r);
// Fixed-point sine
extern cvu_f cvu_fsin(cvu_f x);
// Fixed-point cosine
extern cvu_f cvu_fcos(cvu_f x);
// Fixed-point arcus tangens of x / y.
extern cvu_f cvu_fatan2(cvu_f y, cvu_f x);
#endif

View File

@ -0,0 +1,122 @@
#ifndef CVU_GRAPHICS_H
#define CVU_GRAPHICS_H 1
#include <stdint.h>
#include "cv_graphics.h"
#ifdef CV_SMS
/*
Copy n bytes of data from RAM at src to CRAM at dest.
This function is not reentrant!
The speed of this function depends on the active video mode
and if the screen is active.
*/
extern void cvu_memtocmemcpy(cv_cmemp dest, const void * src, size_t n);
#endif
/*
Copy n bytes of data from RAM at src to VRAM at dest.
This function is not reentrant!
The speed of this function depends on the active video mode
and if the screen is active.
*/
extern void cvu_memtovmemcpy(cv_vmemp dest, const void * src, size_t n);
/*
Copy n bytes of data from VRAM at src to RAM at dest.
This function is not reentrant!
The speed of this function depends on the active video mode
and if the screen is active.
*/
extern void cvu_vmemtomemcpy(void *dest, cv_vmemp src, size_t n);
/*
Set n bytes of VRAM at dest to c.
This function is not reentrant!
The speed of this function depends on the active video mode
and if the screen is active.
*/
extern void cvu_vmemset(cv_vmemp dest, int c, size_t n);
/*
Write an octet to graphics memory at dest.
This function is not reentrant!
*/
extern void cvu_voutb(const uint8_t value, const cv_vmemp dest);
/*
Read an octet from graphics memory at src.
This function is not reentrant!
*/
extern uint8_t cvu_vinb(const cv_vmemp src);
struct cvu_sprite
{
uint8_t y;
uint8_t x;
uint8_t name;
uint8_t tag;
};
#ifdef CV_SMS
struct cvu_sprite4
{
uint8_t y;
uint8_t x;
uint8_t name;
};
#endif
// Write sprite to display memory. Use the location of the sprite table as base. number should be in [0, 31].
inline void cvu_set_sprite(const cv_vmemp base, uint_fast8_t number, const struct cvu_sprite *sprite)
{
cv_set_write_vram_address((base) + (number) * 0x4);
cv_memtovmemcpy_slow((sprite), 4);
}
// Write sprite to display memory (in mode 4). Use the location of the sprite table as base. number should be in [0, 63].
#ifdef CV_SMS
inline void cvu_set_sprite4(const cv_vmemp base, uint_fast8_t number, const struct cvu_sprite4 *sprite)
{
cvu_voutb(sprite->y, base + number);
cv_set_write_vram_address(base + 0x80 + number * 2);
cv_voutb(sprite->x);
cv_voutb(sprite->name);
}
#endif
// Todo: is cvu_get_sprite needed?
// Set the x coordinate of the sprite's upper left corner. x will be clamped to [-32, 255]
extern void cvu_set_sprite_x(struct cvu_sprite *sprite, int x) __preserves_regs(d, e);
extern int cvu_get_sprite_x(const struct cvu_sprite *sprite) __preserves_regs(b, c, d, e);
// Set the y coordinate of the sprite's upper left corner. y will be clamped to [-32, 207]
extern void cvu_set_sprite_y(struct cvu_sprite *sprite, int y) __preserves_regs(d, e);
extern int cvu_get_sprite_y(const struct cvu_sprite *sprite) __preserves_regs(d, e);
// Set them both at once.
extern void cvu_set_sprite_xy(struct cvu_sprite *sprite, int x, int y);
// Set the sprite's color.
inline void cvu_set_sprite_color(struct cvu_sprite *sprite, enum cv_color color)
{
sprite->tag = (sprite->tag & 0x80) | color;
}
extern enum cv_color cvu_get_sprite_color(struct cvu_sprite *sprite);
#endif

View File

@ -0,0 +1,15 @@
#ifndef CVU_INPUT_H
#define CVU_INPUT_H 1
#include <stdint.h>
#include "cv_input.h"
// For the super action controllers this gives the spinner movement (total relative movement since last call, negative for left, positive for right)
// For the roller controller this gives the ball movement (total relative as above).
// Using this function will set a libvu-specific spint handler, so it is incompatible with using a custom spint handler.
int_fast8_t cvu_get_spinner(uint_fast8_t controller);
#endif

View File

@ -0,0 +1,45 @@
#ifndef CVU_SOUND_H
#define CVU_SOUND 1
#include <stdint.h>
#include "cv_sound.h"
extern const uint16_t CVU_TUNING_ISO16_EQUAL[15]; // ISO 16 pitch (A at 440 Hz) with equal tuning.
extern const uint16_t CVU_TUNING_SCIENTIFIC_EQUAL[15]; // Scientific pitch (C at 256 Hz) with equal tuning.
extern const uint8_t CVU_VOLUME_DEFAULT[4];
extern const uint16_t CVU_EMPTY_MUSIC;
// channel holds the channel that will be used to play the music.
// volume is a pointer to an array of loudnesses in Dezibel for p, mp, mf, f.
// tuning is a pointer to an arrays of frequency dividers for the halftones of oktave 0.
// sixteenth_notes_per_second should explain itself.
// notes is a pointer to the music in the following format:
// Every note cosists of 16 bits. The most significant four mark the octave, the next 4
// the halftone (0xf means pause) the next 4 bits give the absolute length. The next 2
// give the relative length. the last 2 bits are the loudness.
// The rest of the structure's members are for internal use by cvu_play_music().
struct cvu_music
{
enum cv_soundchannel channel;
const uint8_t *volume;
const uint16_t *tuning;
uint8_t sixteenth_notes_per_second;
const uint16_t *notes;
uint16_t note_ticks_remaining;
uint16_t pause_ticks_remaining;
};
// This will initialize a cvu_music structure with default values for all
// members except notes.
extern void cvu_init_music(struct cvu_music *music);
// This function should be placed inside the vint handler or triggered by the vint handler.
// It will return false once it is finished playing the music.
extern bool cvu_play_music(struct cvu_music *restrict music);
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -102,11 +102,19 @@ var PLATFORM_PARAMS = {
data_size: 0x400,
stack_end: 0x8000,
extra_preproc_args: ['-I', '/share/include/coleco'],
extra_link_args: ['-k', '/share/lib/coleco',
'-l', 'libcv', '-l', 'libcvu', 'crt0.rel', //'/share/lib/coleco/crt0.rel',
//'-l', 'comp.lib', '-l', 'cvlib.lib', '-l', 'getput.lib', '/share/lib/coleco/crtcv.rel',
//'main.rel'
],
extra_link_args: ['-k', '/share/lib/coleco', '-l', 'libcv', '-l', 'libcvu', 'crt0.rel'],
},
'sg1000': {
rom_start: 0x0000,
code_start: 0x0100,
rom_size: 0xc000,
data_start: 0xc000,
data_size: 0x400,
stack_end: 0xe000,
extra_preproc_args: ['-I', '.', '-D', 'CV_SMS'],
extra_link_args: ['-k', '.', '-l', 'libcv-sms', '-l', 'libcvu-sms', 'crt0-sms.rel'],
extra_link_files: ['libcv-sms.lib', 'libcvu-sms.lib', 'crt0-sms.rel', 'crt0-sms.lst'],
extra_compile_files: ['cv.h','cv_graphics.h','cv_input.h','cv_sound.h','cv_support.h','cvu.h','cvu_c.h','cvu_compression.h','cvu_f.h','cvu_graphics.h','cvu_input.h','cvu_sound.h'],
},
'nes': { //TODO
define: '__NES__',
@ -117,7 +125,7 @@ var PLATFORM_PARAMS = {
'-D', 'NES_CHR_BANKS=0', // TODO: >0 doesn't seem to work
'-D', 'NES_MIRRORING=0',
],
extrafiles: ['crt0.o'],
extra_link_files: ['crt0.o'],
},
'nes-conio': {
cfgfile: 'nes.cfg',
@ -302,9 +310,8 @@ function populateFiles(step:BuildStep, fs, options?:BuildOptions) {
}
}
function populateExtraFiles(step:BuildStep, fs) {
function populateExtraFiles(step:BuildStep, fs, extrafiles) {
// TODO: cache extra files
var extrafiles = step.params.extrafiles;
if (extrafiles) {
for (var i=0; i<extrafiles.length; i++) {
var xfn = extrafiles[i];
@ -824,7 +831,7 @@ function linkLD65(step:BuildStep) {
var cfgfile = '/' + platform + '.cfg';
setupFS(FS, '65-'+platform.split('-')[0]);
populateFiles(step, FS);
populateExtraFiles(step, FS);
populateExtraFiles(step, FS, params.extra_link_files);
var libargs = params.libargs;
var args = ['--cfg-path', '/share/cfg',
'--lib-path', '/share/lib',
@ -955,6 +962,8 @@ function parseIHX(ihx, rom_start, rom_size) {
}
} else if (rectype == 1) {
return output;
} else {
console.log(s); // unknown record type
}
}
}
@ -1048,6 +1057,7 @@ function linkSDLDZ80(step:BuildStep)
var FS = LDZ80['FS'];
setupFS(FS, 'sdcc');
populateFiles(step, FS);
populateExtraFiles(step, FS, params.extra_link_files);
// TODO: coleco hack so that -u flag works
if (step.platform.startsWith("coleco")) {
FS.writeFile('crt0.rel', FS.readFile('/share/lib/coleco/crt0.rel', {encoding:'utf8'}));
@ -1062,9 +1072,11 @@ function linkSDLDZ80(step:BuildStep)
if (params.extra_link_args)
args.push.apply(args, params.extra_link_args);
args.push.apply(args, step.args);
//console.log(args);
execMain(step, LDZ80, args);
var hexout = FS.readFile("main.ihx", {encoding:'utf8'});
var mapout = FS.readFile("main.noi", {encoding:'utf8'});
//console.log(mapout);
putWorkFile("main.ihx", hexout);
putWorkFile("main.noi", mapout);
// return unchanged if no files changed
@ -1096,7 +1108,7 @@ function linkSDLDZ80(step:BuildStep)
}
}
return {
output:parseIHX(hexout, params.rom_start?params.rom_start:params.code_start, params.rom_size),
output:parseIHX(hexout, params.rom_start!==undefined?params.rom_start:params.code_start, params.rom_size),
listings:listings,
errors:errors,
symbolmap:symbolmap,
@ -1196,6 +1208,7 @@ function preprocessMCPP(step:BuildStep) {
var FS = MCPP['FS'];
setupFS(FS, 'sdcc'); // TODO: toolname
populateFiles(step, FS);
populateExtraFiles(step, FS, params.extra_compile_files);
// TODO: make configurable by other compilers
var args = [
"-D", "__8BITWORKSHOP__",

View File

@ -162,10 +162,15 @@ describe('Worker', function() {
compile('sdcc', csource, 'sound_williams-z80', done, 16384, 6, 0);
});
it('should compile coleco skeleton', function(done) {
// TODO: can't do skeleton b/c of dependencies
var csource = ab2str(fs.readFileSync('presets/coleco/text.c'));
compile('sdcc', csource, 'coleco', done, 32768, 15, 0);
});
/* TODO: load extra files
it('should compile sg1000 skeleton', function(done) {
var csource = ab2str(fs.readFileSync('presets/sg1000/text.c'));
compile('sdcc', csource, 'sg1000', done, 32768, 15, 0);
});
*/
it('should compile verilog example', function(done) {
var csource = ab2str(fs.readFileSync('presets/verilog/lfsr.v'));
var msgs = [{code:csource, platform:"verilog", tool:"verilator", dependencies:[], path:'main.v'}];