1
0
mirror of https://github.com/cc65/cc65.git synced 2025-08-08 22:25:28 +00:00

Changed the PC-Engine's configuration file, so that the command line can build 8K, 16K, and 32K carts.

Adjusted the PCE's document, the start-up code, and the PCE library test makefile.  That makefile shows how to post-process the linker's output file.
This commit is contained in:
Greg King
2018-02-23 16:06:49 -05:00
parent 83890e56eb
commit 3a0506ccb3
5 changed files with 115 additions and 84 deletions

View File

@@ -1,34 +1,29 @@
# linker config to produce simple NEC PC-Engine cartridge (.pce) # linker config. to produce a NEC PC-Engine 8K, 16K, or 32K image (.bin)
SYMBOLS { SYMBOLS {
__CARTSIZE__: type = weak, value = $2000; # $2000, $4000, or $8000
__STACKSIZE__: type = weak, value = $0300; # 3 pages stack __STACKSIZE__: type = weak, value = $0300; # 3 pages stack
} }
MEMORY { MEMORY {
# FIXME: is this correct? the first 3? bytes cant be used? ZP: file = "", start = $0000, size = $0100, define = yes;
ZP: file = "", start = $0003, size = $00FD, type = rw, define = yes; # RAM bank
MAIN: file = "", start = $2200, size = $1E00 - __STACKSIZE__, define = yes;
# reset-bank and hardware vectors # ROM banks, before swapping, and after mapping
ROM0: file = %O, start = $E000, size = $1FF6, fill = yes, define = yes; ROM: file = %O, start = $10000 - __CARTSIZE__, size = __CARTSIZE__, fill = yes, fillval = $FF;
ROMV: file = %O, start = $FFF6, size = $000A, fill = yes;
# first RAM page (also contains stack and zeropage)
RAM: file = "", start = $2200, size = $1e00, define = yes;
} }
SEGMENTS { SEGMENTS {
ZEROPAGE: load = ZP, type = zp, define = yes; ZEROPAGE: load = ZP, type = zp;
EXTZP: load = ZP, type = zp, define = yes, optional = yes; EXTZP: load = ZP, type = zp, optional = yes;
APPZP: load = ZP, type = zp, define = yes, optional = yes; APPZP: load = ZP, type = zp, optional = yes;
STARTUP: load = ROM0, type = ro, define = yes; DATA: load = ROM, run = MAIN, type = rw, define = yes;
ONCE: load = ROM0, type = ro, optional = yes; INIT: load = MAIN, type = bss, optional = yes;
CODE: load = ROM0, type = ro, define = yes; BSS: load = MAIN, type = bss, define = yes;
RODATA: load = ROM0, type = ro, define = yes; RODATA: load = ROM, type = ro;
DATA: load = ROM0, run = RAM, type = rw, define = yes; CODE: load = ROM, type = ro;
BSS: load = RAM, type = bss, define = yes; LOWCODE: load = ROM, type = ro, optional = yes;
VECTORS: load = ROMV, type = rw, define = yes; ONCE: load = ROM, type = ro, optional = yes;
STARTUP: load = ROM, type = ro, start = $FFF6 - $0066;
VECTORS: load = ROM, type = ro, start = $FFF6;
} }
FEATURES { FEATURES {
CONDES: type = constructor, CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__, label = __CONSTRUCTOR_TABLE__,

View File

@@ -3,9 +3,9 @@
<article> <article>
<title>PC-Engine (TurboGrafx) System specific information for cc65 <title>PC-Engine (TurboGrafx) System specific information for cc65
<author> <author><url url="mailto:groepaz@gmx.net" name="Groepaz/Hitmen">,<newline>
<url url="mailto:groepaz@gmx.net" name="Groepaz/Hitmen"> <url url="mailto:greg.king5@verizon.net" name="Greg King">
<date>2016-09-29 <date>2018-02-12
<abstract> <abstract>
An overview over the PCE runtime system as it is implemented for the An overview over the PCE runtime system as it is implemented for the
@@ -30,11 +30,36 @@ more than one platform. Please see the function reference for more
information. information.
<sect>Binary format<p> <sect>Binary format<p>
The standard binary output format generated by the linker for the PCE target The binary output file generated by the linker, for the PCE target, is an
is a cartridge image with no header. It is of course possible to change this image, with no header, that has 8K bytes in the wrong place. That file must be
behaviour by using a modified startup file and linker config. post-processed; the 8K at the end must be moved to the front of the image.
On POSIX systems, the <tt/dd/ command and the shell give a convenient way to do
it. Here is an example of their use:
<tscreen><verb>
dd if=conio.bin bs=8K skip=3 > conio.pce
dd if=conio.bin bs=8K count=3 >> conio.pce
</verb></tscreen>
The first command grabs the last 8K of a 32K file, and writes it as the first
part of a new file. The second command reads all but the last part of the old
file, and appends it to the new file.
<tscreen><verb>
+--------+--------+--------+--------+
| Bank 1 | Bank 2 | Bank 3 | Bank 0 | &lt;-- "conio.bin"
+--------+--------+--------+--------+
+--------+--------+--------+--------+
| Bank 0 | Bank 1 | Bank 2 | Bank 3 | &lt;-- "conio.pce"
+--------+--------+--------+--------+
</verb></tscreen>
<em/Note/: That <tt/.pce/ file shows the format of the ROM cartridge that is
plugged into a PC-Engine. But, that <tt/.bin/ file shows what programs
actually see when they execute the code in that cartridge.
<sect>Memory layout<p> <sect>Memory layout<p>
@@ -52,19 +77,23 @@ Special locations:
<tag/Stack/ <tag/Stack/
The C runtime stack is located in system RAM at &dollar;3FFF and growing downwards. The C runtime stack is located in system RAM at &dollar;3FFF and growing downwards.
<tag/BSS and Data/ <tag/Data and BSS/
The Data (initialized variables) and BSS (uninitialized variables) sections are
The BSS (uninitialized variables) and Data (initialized variables) sections are placed one after the other into system RAM at &dollar;2200.
placed one after the other into system RAM at &dollar;2000.
<tag/Heap/ <tag/Heap/
The C heap is located after the end of the Data section and grows towards the C The C heap is located after the end of the BSS section; and, grows towards the C
runtime stack. runtime stack.
<tag/Code/ <tag/Code/
The startup code is located at &dollar;E000 in the System/Hardware bank. Further In an 8K ROM cartridge, code and read-only data are located between
code can be placed in other ROM banks, this must be done manually however. &dollar;E000 and &dollar;FFF5 in the System bank.
In a 16K cartridge, code and read-only data are located between &dollar;C000
and &dollar;FFF5.
In a 32K cartridge, code and read-only data are located between &dollar;8000
and &dollar;FFF5.
</descrip><p> </descrip><p>
@@ -171,7 +200,8 @@ following functions (and a few others):
<sect>Other hints<p> <sect>Other hints<p>
<itemize> <itemize>
<item>a good emulator to use for PC-Engine is "mednafen" (<url url="http://mednafen.fobby.net/">) <item><url url="https://mednafen.github.io/" name= "Mednafen"> is a good
emulator to use for the PC-Engine.
</itemize> </itemize>
some useful resources on PCE coding: some useful resources on PCE coding:
@@ -210,6 +240,3 @@ freely, subject to the following restrictions:
</enum> </enum>
</article> </article>

View File

@@ -4,33 +4,26 @@
; by Groepaz/Hitmen <groepaz@gmx.net> ; by Groepaz/Hitmen <groepaz@gmx.net>
; based on code by Ullrich von Bassewitz <uz@cc65.org> ; based on code by Ullrich von Bassewitz <uz@cc65.org>
; ;
; This must be the *first* file on the linker command line ; 2018-02-11, Greg King
; ;
.export _exit .export _exit
.export __STARTUP__ : absolute = 1 ; Mark as startup .export __STARTUP__ : absolute = 1 ; Mark as startup
.import initlib, donelib .import initlib, donelib
.import push0, _main, zerobss .import push0, _main
.import initheap
.import IRQStub .import IRQStub
; Linker generated ; Linker-generated
.import __RAM_START__, __RAM_SIZE__ .import __CARTSIZE__
.import __ROM0_START__, __ROM0_SIZE__ .import __DATA_LOAD__, __DATA_RUN__, __DATA_SIZE__
.import __ROM_START__, __ROM_SIZE__ .import __BSS_RUN__, __BSS_SIZE__
.import __STARTUP_LOAD__,__STARTUP_RUN__, __STARTUP_SIZE__ .import __MAIN_START__, __MAIN_SIZE__, __STACKSIZE__
.import __CODE_LOAD__,__CODE_RUN__, __CODE_SIZE__
.import __RODATA_LOAD__,__RODATA_RUN__, __RODATA_SIZE__
.import __DATA_LOAD__,__DATA_RUN__, __DATA_SIZE__
.import __BSS_SIZE__
.include "pce.inc" .include "pce.inc"
.include "extzp.inc" .include "extzp.inc"
.importzp sp .importzp sp
.importzp ptr1,ptr2
.importzp tmp1,tmp2,tmp3
; ------------------------------------------------------------------------ ; ------------------------------------------------------------------------
; Place the startup code in a special segment. ; Place the startup code in a special segment.
@@ -53,29 +46,27 @@ start:
ldx #$FF ; Stack top ($21FF) ldx #$FF ; Stack top ($21FF)
txs txs
; At startup all MPRs are set to 0, so init them ; At power-on, most MPRs have random values; so, initiate them.
lda #$ff lda #$FF
tam #%00000001 ; 0000-1FFF = Hardware page tam #%00000001 ; $0000-$1FFF = Hardware bank
lda #$F8 lda #$F8
tam #%00000010 ; 2000-3FFF = Work RAM tam #%00000010 ; $2000-$3FFF = Work RAM
; FIXME: setup a larger block of memory to use with C-code
;lda #$F7 ;lda #$F7
;tam #%00000100 ; 4000-5FFF = Save RAM ;tam #%00000100 ; $4000-$47FF = 2K Battery-backed RAM
;lda #1
;tam #%00001000 ; 6000-7FFF Page 2
;lda #2
;tam #%00010000 ; 8000-9FFF Page 3
;lda #3
;tam #%00100000 ; A000-BFFF Page 4
;lda #4 ;lda #4
;tam #%01000000 ; C000-DFFF Page 5 ;tam #%00001000 ; $6000-$7FFF
;lda #0
;tam #%10000000 ; e000-fFFF hucard/syscard bank 0
; Clear work RAM (2000-3FFF) lda #$01
stz <$00 ldx #>$8000
tii $2000, $2001, $1FFF cpx #>__CARTSIZE__
bcc @L1 ;(blt)
tam #%00010000 ; $8000-$9FFF = ROM bank 1 (32K block of ROM)
inc a
tam #%00100000 ; $A000-$BFFF = ROM bank 2
inc a
@L1: tam #%01000000 ; $C000-$DFFF = ROM bank 3 (32K) or 1 (16K)
;lda #$00 ; (The reset default)
;tam #%10000000 ; $E000-$FFFF hucard/syscard bank 0
; Initialize hardware ; Initialize hardware
stz TIMER_CTRL ; Timer off stz TIMER_CTRL ; Timer off
@@ -91,15 +82,16 @@ start:
lda #$05 lda #$05
sta IRQ_MASK ; IRQ1=on sta IRQ_MASK ; IRQ1=on
; Clear the BSS data
jsr zerobss
; Copy the .data segment to RAM ; Copy the .data segment to RAM
tii __DATA_LOAD__, __DATA_RUN__, __DATA_SIZE__ tii __DATA_LOAD__, __DATA_RUN__, __DATA_SIZE__
; Clear the .bss segment
stz __BSS_RUN__
tii __BSS_RUN__, __BSS_RUN__ + 1, __BSS_SIZE__ - 1
; Set up the stack ; Set up the stack
lda #<(__RAM_START__+__RAM_SIZE__) lda #<(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__)
ldx #>(__RAM_START__+__RAM_SIZE__) ldx #>(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__)
sta sp sta sp
stx sp + 1 stx sp + 1

View File

@@ -1,12 +1,29 @@
.PHONY: all clean test .PHONY: all clean test
# Size of cartridge to generate.
# Possible values:
# 8K = 0x2000
# 16K = 0x4000
# 32K = 0x8000
CARTSIZE := 0x2000
ifeq (${CARTSIZE},0x8000)
COUNT := 3
else
COUNT := 1
endif
all: conio.pce all: conio.pce
conio.pce: conio.c %.pce: %.bin
../../../bin/cl65 -t pce conio.c --mapfile conio.map -o conio.pce dd if=$< bs=8K skip=${COUNT} > $@
dd if=$< bs=8K count=${COUNT} >> $@
%.bin: %.c ../../../lib/pce.lib
../../../bin/cl65 -t pce $< -Wl -D__CARTSIZE__=${CARTSIZE} -m $*.map -o $@
clean: clean:
$(RM) conio.o conio.pce conio.map $(RM) conio.o conio.???
test: conio.pce test: conio.pce
mednafen -force_module pce conio.pce mednafen -force_module pce $<

View File

@@ -45,7 +45,7 @@ void main(void)
p[8],p[9],p[10],p[11],p[12],p[13],p[14],p[15] p[8],p[9],p[10],p[11],p[12],p[13],p[14],p[15]
); );
} }
memcpy(p, main, 0); /* test that a zero length doesn't copy 64K */ memcpy(p, main, i = 0); /* test that a zero length doesn't copy 64K */
gotoxy(0,ysize - 1); gotoxy(0,ysize - 1);
for (i = 0; i < xsize; ++i) { for (i = 0; i < xsize; ++i) {