@@ -0,0 +1,94 @@
/*****************************************************************************/
/* */
/* pce.h */
/* */
/* PC-Engine system specific definitions */
/* */
/* */
/* */
/* (C) 2015 Groepaz/Hitmen */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/

#ifndef _PCE_H
#define _PCE_H

/* Check for errors */
#if !defined(__PCE__)
# error This module may only be used when compiling for the PCE!
#endif

#define CH_HLINE 1
#define CH_VLINE 2
#define CH_CROSS 3
#define CH_ULCORNER 4
#define CH_URCORNER 5
#define CH_LLCORNER 6
#define CH_LRCORNER 7
#define CH_TTEE 8
#define CH_BTEE 9
#define CH_LTEE 10
#define CH_RTEE 11

#define CH_ENTER 13
#define CH_PI 18

/* Color defines (CBM compatible, for conio) */
#define COLOR_BLACK 0x00
#define COLOR_WHITE 0x01
#define COLOR_RED 0x02
#define COLOR_CYAN 0x03
#define COLOR_VIOLET 0x04
#define COLOR_GREEN 0x05
#define COLOR_BLUE 0x06
#define COLOR_YELLOW 0x07
#define COLOR_ORANGE 0x08
#define COLOR_BROWN 0x09
#define COLOR_LIGHTRED 0x0A
#define COLOR_GRAY1 0x0B
#define COLOR_GRAY2 0x0C
#define COLOR_LIGHTGREEN 0x0D
#define COLOR_LIGHTBLUE 0x0E
#define COLOR_GRAY3 0x0F

#define TV_NTSC 0
#define TV_PAL 1
#define TV_OTHER 2

/* No support for dynamically loadable drivers */
#define DYN_DRV 0

/* The addresses of the static drivers */
extern void pce_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */

#define JOY_FIRE_B 5
#define JOY_SELECT 6
#define JOY_RUN 7

void waitvblank (void);
/* Wait for the vertical blanking */

/* NOTE: all PCE are NTSC */
#define get_tv() TV_NTSC
/* Return the video mode the machine is using. */

/* End of pce.h */
#endif
@@ -99,6 +99,9 @@ unsigned _clocks_per_sec (void);
#elif defined(__NES__)
# define CLK_TCK 50 /* POSIX */
# define CLOCKS_PER_SEC 50 /* ANSI */
#elif defined(__PCE__)
# define CLK_TCK 60 /* POSIX */
# define CLOCKS_PER_SEC 60 /* ANSI */
#elif defined(__GEOS__)
# define CLK_TCK 1 /* POSIX */
# define CLOCKS_PER_SEC 1 /* ANSI */
@@ -25,6 +25,7 @@ TARGETS = apple2 \
lynx \
nes \
osic1p \
pce \
sim6502 \
sim65c02 \
supervision
@@ -109,7 +109,7 @@ inv_drv:

copy: lda (ptr1),y
iny
set: sta joy_vectors,x
sta joy_vectors,x
inx
rts

@@ -0,0 +1,18 @@
;
; Screen size variables
;
.include "pce.inc"

.export screensize
screensize:
ldx xsize
ldy ysize
rts

; FIXME: changing the video mode allows for different screen sizes

.rodata
.export xsize, ysize

xsize: .byte charsperline
ysize: .byte screenrows
@@ -0,0 +1,32 @@
;
; Ullrich von Bassewitz, 08.08.1998
;
; void chlinexy (unsigned char x, unsigned char y, unsigned char length);
; void chline (unsigned char length);
;

.export _chlinexy, _chline
.import popa, _gotoxy, cputdirect
.importzp tmp1

.include "pce.inc"

_chlinexy:
pha ; Save the length
jsr popa ; Get y
jsr _gotoxy ; Call this one, will pop params
pla ; Restore the length

_chline:
cmp #0 ; Is the length zero?
beq L9 ; Jump if done
sta tmp1
L1: lda #CH_HLINE ; Horizontal line, screen code
jsr cputdirect ; Direct output
dec tmp1
bne L1
L9: rts




@@ -0,0 +1,32 @@
;
; clock_t clock (void);
;

.include "pce.inc"
.include "extzp.inc"

.forceimport ticktock
.export _clock
.importzp sreg

.proc _clock

lda tickcount+3
sta sreg+1
lda tickcount+2
sta sreg
ldx tickcount+1
lda tickcount
rts

.endproc

.constructor initclock, 24

initclock:
lda #0
ldx #3
@lp: sta tickcount,x
dex
bpl @lp
rts
@@ -0,0 +1,38 @@

.include "pce.inc"
.include "extzp.inc"

.import plot
.export _clrscr
_clrscr:

st0 #VDC_MAWR
st1 #<$0000
st2 #>$0000

st0 #VDC_VWR
ldy #$40
rowloop:
ldx #$80
colloop:
lda #' '
sta a:VDC_DATA_LO
lda #$02
sta a:VDC_DATA_HI

dex
bne colloop
dey
bne rowloop

; Go to the home position.

stz CURS_X
stz CURS_Y
jmp plot

;-------------------------------------------------------------------------------
; force the init constructor to be imported

.import initconio
conio_init = initconio
@@ -0,0 +1,66 @@
;
; unsigned char __fastcall__ textcolor (unsigned char color);
; unsigned char __fastcall__ bgcolor (unsigned char color);
; unsigned char __fastcall__ bordercolor (unsigned char color);
;


.export _textcolor, _bgcolor, _bordercolor

.include "pce.inc"
.include "extzp.inc"

_textcolor:
ldx CHARCOLOR ; get old value
sta CHARCOLOR ; set new value
txa
rts

_bgcolor:
ldx BGCOLOR ; get old value
sta BGCOLOR ; set new value
asl a
tay

stz VCE_ADDR_LO
stz VCE_ADDR_HI
lda colors,y
sta VCE_DATA_LO
lda colors+1,y
sta VCE_DATA_HI

txa
rts

_bordercolor:
lda #0
tax
rts

.rodata
.export colors

colors:
; G R B
.word ((0<<6)+(0<<3)+(0)) ; 0 black
.word ((7<<6)+(7<<3)+(7)) ; 1 white
.word ((0<<6)+(7<<3)+(0)) ; 2 red
.word ((7<<6)+(0<<3)+(7)) ; 3 cyan
.word ((0<<6)+(5<<3)+(7)) ; 4 violett
.word ((7<<6)+(0<<3)+(0)) ; 5 green
.word ((0<<6)+(0<<3)+(7)) ; 6 blue
.word ((7<<6)+(7<<3)+(0)) ; 7 yellow
.word ((5<<6)+(7<<3)+(0)) ; 8 orange
.word ((3<<6)+(4<<3)+(3)) ; 9 brown
.word ((4<<6)+(7<<3)+(4)) ; a light red
.word ((3<<6)+(3<<3)+(3)) ; b dark grey
.word ((4<<6)+(4<<3)+(4)) ; c middle grey
.word ((7<<6)+(4<<3)+(4)) ; d light green
.word ((4<<6)+(4<<3)+(7)) ; e light blue
.word ((6<<6)+(6<<3)+(6)) ; f light gray

;-------------------------------------------------------------------------------
; force the init constructor to be imported

.import initconio
conio_init = initconio
@@ -0,0 +1,124 @@
.include "pce.inc"
.include "extzp.inc"

.import vce_init
.import psg_init
.import vdc_init

.constructor initconio, 24

.macpack longbranch

initconio:
jsr vce_init
jsr psg_init
jsr conio_init
jsr set_palette

st0 #VDC_CR
st1 #<$0088
st2 #>$0088
rts

.import colors
set_palette:
stz VCE_ADDR_LO
stz VCE_ADDR_HI

ldx #0
@lp:
ldy #16
@lp1:
lda colors,x
sta VCE_DATA_LO
lda colors+1,x
sta VCE_DATA_HI
dey
bne @lp1

inx
inx
cpx #16*2
jne @lp

stz VCE_ADDR_LO
stz VCE_ADDR_HI
stz VCE_DATA_LO
stz VCE_DATA_HI

rts

;----------------------------------------------------------------------------
;
;----------------------------------------------------------------------------

.importzp ptr1, tmp1
conio_init:
; Load font
st0 #VDC_MAWR
st1 #<$2000
st2 #>$2000

; ptr to font data
lda #<font
sta ptr1
lda #>font
sta ptr1+1

st0 #VDC_VWR ; VWR

lda #0
sta tmp1
jsr copy

lda #<font
sta ptr1
lda #>font
sta ptr1+1

lda #$ff
sta tmp1
jsr copy


ldx #0
stx BGCOLOR
inx
stx CHARCOLOR


rts

copy:
ldy #$80 ; 128 chars
charloop:
ldx #$08 ; 8 bytes/char
lineloop:
lda (ptr1)
eor tmp1
sta a:VDC_DATA_LO ; bitplane 0
stz a:VDC_DATA_HI ; bitplane 1

clc ; increment font pointer
lda ptr1
adc #$01
sta ptr1
lda ptr1+1
adc #$00
sta ptr1+1
dex
bne lineloop ; next bitplane 0 byte
ldx #$08 ; fill bitplane 2/3 with 0
fillloop:
st1 #$00
st2 #$00
dex
bne fillloop ; next byte
dey
bne charloop ; next character

rts

.rodata
font:
.include "vga.inc"
@@ -0,0 +1,99 @@
;
; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (char c);
;

.export _cputcxy, _cputc, cputdirect, putchar
.export newline, plot
.import popa, _gotoxy
.import PLOT
.import xsize

.importzp tmp3,tmp4

.include "pce.inc"
.include "extzp.inc"

_cputcxy:
pha ; Save C
jsr popa ; Get Y
jsr _gotoxy ; Set cursor, drop x
pla ; Restore C

; Plot a character - also used as internal function

_cputc: cmp #$0d ; CR?
bne L1
lda #0
sta CURS_X
beq plot ; Recalculate pointers

L1: cmp #$0a ; LF?
beq newline ; Recalculate pointers

; Printable char of some sort

cputdirect:
jsr putchar ; Write the character to the screen

; Advance cursor position

advance:
ldy CURS_X
iny
cpy xsize
bne L3
jsr newline ; new line
ldy #0 ; + cr
L3: sty CURS_X
jmp plot

newline:
inc CURS_Y

; Set cursor position, calculate RAM pointers

plot: ldy CURS_X
ldx CURS_Y
clc
jmp PLOT ; Set the new cursor

; Write one character to the screen without doing anything else, return X
; position in Y

putchar:

ora RVS ; Set revers bit

tax

st0 #VDC_MAWR ; Memory Adress Write

lda SCREEN_PTR
sta a:VDC_DATA_LO

lda SCREEN_PTR + 1
sta a:VDC_DATA_HI

st0 #VDC_VWR ; VWR

txa
sta a:VDC_DATA_LO ; character

lda CHARCOLOR

asl a
asl a
asl a
asl a

ora #$02
sta a:VDC_DATA_HI

rts

;-------------------------------------------------------------------------------
; force the init constructor to be imported

.import initconio
conio_init = initconio
@@ -0,0 +1,178 @@
;
; Startup code for cc65 (PCEngine version)
;
; by Groepaz/Hitmen <groepaz@gmx.net>
; based on code by Ullrich von Bassewitz <uz@cc65.org>
;
; This must be the *first* file on the linker command line
;

.export _exit
.export __STARTUP__ : absolute = 1 ; Mark as startup

.import initlib, donelib
.import push0, _main, zerobss
.import initheap
.import IRQStub

; Linker generated
.import __RAM_START__, __RAM_SIZE__
.import __ROM0_START__, __ROM0_SIZE__
.import __ROM_START__, __ROM_SIZE__
.import __STARTUP_LOAD__,__STARTUP_RUN__, __STARTUP_SIZE__
.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 "extzp.inc"

.importzp sp
.importzp ptr1,ptr2
.importzp tmp1,tmp2,tmp3

; ------------------------------------------------------------------------
; Place the startup code in a special segment.

.segment "STARTUP"

start:

; setup the CPU and System-IRQ

; Initialize CPU

sei
nop
csh ; set high speed CPU mode
nop
cld
nop

; Setup stack and memory mapping
ldx #$FF ; Stack top ($21FF)
txs

; at startup all MPRs are set to 0, so init them
lda #$ff
tam #%00000001 ; 0000-1FFF = Hardware page
lda #$F8
tam #%00000010 ; 2000-3FFF = Work RAM

; FIXME: setup a larger block of memory to use with C-code
;lda #$F7
;tam #%00000100 ; 4000-5FFF = Save 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
;tam #%01000000 ; C000-DFFF Page 5
;lda #0
;tam #%10000000 ; e000-fFFF hucard/syscard bank 0

; Clear work RAM (2000-3FFF)
stz <$00
tii $2000, $2001, $1FFF

; Initialize hardware
stz TIMER_CTRL ; Timer off
lda #$07
sta IRQ_MASK ; Interrupts off
stz IRQ_STATUS ; Acknowledge timer

; FIXME; i dont know why the heck this one doesnt work when called from a constructor :/
.import vdc_init
jsr vdc_init

; Turn on background and VD interrupt/IRQ1
lda #$05
sta IRQ_MASK ; IRQ1=on

; Clear the BSS data
jsr zerobss

; Copy the .data segment to RAM
lda #<(__DATA_LOAD__)
sta ptr1
lda #>(__DATA_LOAD__)
sta ptr1+1
lda #<(__DATA_RUN__)
sta ptr2
lda #>(__DATA_RUN__)
sta ptr2+1

ldx #>(__DATA_SIZE__)
@l2:
beq @s1 ; no more full pages

; copy one page
ldy #0
@l1:
lda (ptr1),y
sta (ptr2),y
iny
bne @l1

inc ptr1+1
inc ptr2+1

dex
bne @l2

; copy remaining bytes
@s1:
; copy one page
ldy #0
@l3:
lda (ptr1),y
sta (ptr2),y
iny
cpy #<(__DATA_SIZE__)
bne @l3

; setup the stack
lda #<(__RAM_START__+__RAM_SIZE__)
sta sp
lda #>(__RAM_START__+__RAM_SIZE__)
sta sp + 1

; Call module constructors
jsr initlib

cli ; allow IRQ only after constructors have run

; Pass an empty command line
jsr push0 ; argc
jsr push0 ; argv

ldy #4 ; Argument size
jsr _main ; call the users code

; Call module destructors. This is also the _exit entry.
_exit:
jsr donelib ; Run module destructors

; reset the PCEngine (start over)
jmp start

_nmi:
rti

.export initmainargs
initmainargs:
rts

; ------------------------------------------------------------------------
; hardware vectors
; ------------------------------------------------------------------------
.segment "VECTORS"

.word IRQStub ; $fff6 IRQ2 (External IRQ, BRK)
.word IRQStub ; $fff8 IRQ1 (VDC)
.word IRQStub ; $fffa Timer
.word _nmi ; $fffc NMI
.word start ; $fffe reset
@@ -0,0 +1,161 @@
;
; Stefan Haubenthal with minor changes from Ullrich von Bassewitz, 2003-05-02
;
; Character specification table.
;

.include "ctype.inc"

; The tables are readonly, put them into the rodata segment

.rodata

; The following 256 byte wide table specifies attributes for the isxxx type
; of functions. Doing it by a table means some overhead in space, but it
; has major advantages:
;
; * It is fast. If it were'nt for the slow parameter passing of cc65, one
; could even define macros for the isxxx functions (this is usually
; done on other platforms).
;
; * It is highly portable. The only unportable part is the table itself,
; all real code goes into the common library.
;
; * We save some code in the isxxx functions.


__ctype:
.repeat 2
.byte CT_CTRL ; 0/00 ___ctrl_@___
.byte CT_CTRL ; 1/01 ___ctrl_A___
.byte CT_CTRL ; 2/02 ___ctrl_B___
.byte CT_CTRL ; 3/03 ___ctrl_C___
.byte CT_CTRL ; 4/04 ___ctrl_D___
.byte CT_CTRL ; 5/05 ___ctrl_E___
.byte CT_CTRL ; 6/06 ___ctrl_F___
.byte CT_CTRL ; 7/07 ___ctrl_G___
.byte CT_CTRL ; 8/08 ___ctrl_H___
.byte CT_CTRL | CT_OTHER_WS | CT_SPACE_TAB
; 9/09 ___ctrl_I___
.byte CT_CTRL | CT_OTHER_WS ; 10/0a ___ctrl_J___
.byte CT_CTRL | CT_OTHER_WS ; 11/0b ___ctrl_K___
.byte CT_CTRL | CT_OTHER_WS ; 12/0c ___ctrl_L___
.byte CT_CTRL | CT_OTHER_WS ; 13/0d ___ctrl_M___
.byte CT_CTRL ; 14/0e ___ctrl_N___
.byte CT_CTRL ; 15/0f ___ctrl_O___
.byte CT_CTRL ; 16/10 ___ctrl_P___
.byte CT_CTRL ; 17/11 ___ctrl_Q___
.byte CT_CTRL ; 18/12 ___ctrl_R___
.byte CT_CTRL ; 19/13 ___ctrl_S___
.byte CT_CTRL ; 20/14 ___ctrl_T___
.byte CT_CTRL ; 21/15 ___ctrl_U___
.byte CT_CTRL ; 22/16 ___ctrl_V___
.byte CT_CTRL ; 23/17 ___ctrl_W___
.byte CT_CTRL ; 24/18 ___ctrl_X___
.byte CT_CTRL ; 25/19 ___ctrl_Y___
.byte CT_CTRL ; 26/1a ___ctrl_Z___
.byte CT_CTRL ; 27/1b ___ctrl_[___
.byte CT_CTRL ; 28/1c ___ctrl_\___
.byte CT_CTRL ; 29/1d ___ctrl_]___
.byte CT_CTRL ; 30/1e ___ctrl_^___
.byte CT_CTRL ; 31/1f ___ctrl_____
.byte CT_SPACE | CT_SPACE_TAB ; 32/20 ___SPACE___
.byte CT_NONE ; 33/21 _____!_____
.byte CT_NONE ; 34/22 _____"_____
.byte CT_NONE ; 35/23 _____#_____
.byte CT_NONE ; 36/24 _____$_____
.byte CT_NONE ; 37/25 _____%_____
.byte CT_NONE ; 38/26 _____&_____
.byte CT_NONE ; 39/27 _____'_____
.byte CT_NONE ; 40/28 _____(_____
.byte CT_NONE ; 41/29 _____)_____
.byte CT_NONE ; 42/2a _____*_____
.byte CT_NONE ; 43/2b _____+_____
.byte CT_NONE ; 44/2c _____,_____
.byte CT_NONE ; 45/2d _____-_____
.byte CT_NONE ; 46/2e _____._____
.byte CT_NONE ; 47/2f _____/_____
.byte CT_DIGIT | CT_XDIGIT ; 48/30 _____0_____
.byte CT_DIGIT | CT_XDIGIT ; 49/31 _____1_____
.byte CT_DIGIT | CT_XDIGIT ; 50/32 _____2_____
.byte CT_DIGIT | CT_XDIGIT ; 51/33 _____3_____
.byte CT_DIGIT | CT_XDIGIT ; 52/34 _____4_____
.byte CT_DIGIT | CT_XDIGIT ; 53/35 _____5_____
.byte CT_DIGIT | CT_XDIGIT ; 54/36 _____6_____
.byte CT_DIGIT | CT_XDIGIT ; 55/37 _____7_____
.byte CT_DIGIT | CT_XDIGIT ; 56/38 _____8_____
.byte CT_DIGIT | CT_XDIGIT ; 57/39 _____9_____
.byte CT_NONE ; 58/3a _____:_____
.byte CT_NONE ; 59/3b _____;_____
.byte CT_NONE ; 60/3c _____<_____
.byte CT_NONE ; 61/3d _____=_____
.byte CT_NONE ; 62/3e _____>_____
.byte CT_NONE ; 63/3f _____?_____

.byte CT_NONE ; 64/40 _____@_____
.byte CT_UPPER | CT_XDIGIT ; 65/41 _____A_____
.byte CT_UPPER | CT_XDIGIT ; 66/42 _____B_____
.byte CT_UPPER | CT_XDIGIT ; 67/43 _____C_____
.byte CT_UPPER | CT_XDIGIT ; 68/44 _____D_____
.byte CT_UPPER | CT_XDIGIT ; 69/45 _____E_____
.byte CT_UPPER | CT_XDIGIT ; 70/46 _____F_____
.byte CT_UPPER ; 71/47 _____G_____
.byte CT_UPPER ; 72/48 _____H_____
.byte CT_UPPER ; 73/49 _____I_____
.byte CT_UPPER ; 74/4a _____J_____
.byte CT_UPPER ; 75/4b _____K_____
.byte CT_UPPER ; 76/4c _____L_____
.byte CT_UPPER ; 77/4d _____M_____
.byte CT_UPPER ; 78/4e _____N_____
.byte CT_UPPER ; 79/4f _____O_____
.byte CT_UPPER ; 80/50 _____P_____
.byte CT_UPPER ; 81/51 _____Q_____
.byte CT_UPPER ; 82/52 _____R_____
.byte CT_UPPER ; 83/53 _____S_____
.byte CT_UPPER ; 84/54 _____T_____
.byte CT_UPPER ; 85/55 _____U_____
.byte CT_UPPER ; 86/56 _____V_____
.byte CT_UPPER ; 87/57 _____W_____
.byte CT_UPPER ; 88/58 _____X_____
.byte CT_UPPER ; 89/59 _____Y_____
.byte CT_UPPER ; 90/5a _____Z_____
.byte CT_NONE ; 91/5b _____[_____
.byte CT_NONE ; 92/5c _____\_____
.byte CT_NONE ; 93/5d _____]_____
.byte CT_NONE ; 94/5e _____^_____
.byte CT_NONE ; 95/5f _UNDERLINE_
.byte CT_NONE ; 96/60 ___grave___
.byte CT_LOWER | CT_XDIGIT ; 97/61 _____a_____
.byte CT_LOWER | CT_XDIGIT ; 98/62 _____b_____
.byte CT_LOWER | CT_XDIGIT ; 99/63 _____c_____
.byte CT_LOWER | CT_XDIGIT ; 100/64 _____d_____
.byte CT_LOWER | CT_XDIGIT ; 101/65 _____e_____
.byte CT_LOWER | CT_XDIGIT ; 102/66 _____f_____
.byte CT_LOWER ; 103/67 _____g_____
.byte CT_LOWER ; 104/68 _____h_____
.byte CT_LOWER ; 105/69 _____i_____
.byte CT_LOWER ; 106/6a _____j_____
.byte CT_LOWER ; 107/6b _____k_____
.byte CT_LOWER ; 108/6c _____l_____
.byte CT_LOWER ; 109/6d _____m_____
.byte CT_LOWER ; 110/6e _____n_____
.byte CT_LOWER ; 111/6f _____o_____
.byte CT_LOWER ; 112/70 _____p_____
.byte CT_LOWER ; 113/71 _____q_____
.byte CT_LOWER ; 114/72 _____r_____
.byte CT_LOWER ; 115/73 _____s_____
.byte CT_LOWER ; 116/74 _____t_____
.byte CT_LOWER ; 117/75 _____u_____
.byte CT_LOWER ; 118/76 _____v_____
.byte CT_LOWER ; 119/77 _____w_____
.byte CT_LOWER ; 120/78 _____x_____
.byte CT_LOWER ; 121/79 _____y_____
.byte CT_LOWER ; 122/7a _____z_____
.byte CT_NONE ; 123/7b _____{_____
.byte CT_NONE ; 124/7c _____|_____
.byte CT_NONE ; 125/7d _____}_____
.byte CT_NONE ; 126/7e _____~_____
.byte CT_OTHER_WS ; 127/7f ____DEL____
.endrepeat


@@ -0,0 +1,32 @@
;
; Ullrich von Bassewitz, 08.08.1998
;
; void cvlinexy (unsigned char x, unsigned char y, unsigned char length);
; void cvline (unsigned char length);
;

.export _cvlinexy, _cvline
.import popa, _gotoxy, putchar, newline
.importzp tmp1

.include "pce.inc"

_cvlinexy:
pha ; Save the length
jsr popa ; Get y
jsr _gotoxy ; Call this one, will pop params
pla ; Restore the length and run into _cvline

_cvline:
cmp #0 ; Is the length zero?
beq L9 ; Jump if done
sta tmp1
L1: lda #CH_VLINE ; Vertical bar
jsr putchar ; Write, no cursor advance
jsr newline ; Advance cursor to next line
dec tmp1
bne L1
L9: rts



@@ -0,0 +1,18 @@
;
; extzp.inc for the PC-Engine
;
; Groepaz/Hitmen, 2015-11-19
;
; Assembler include file that imports the runtime zero page locations used
; by the PC-Engine runtime, ready for usage in asm code.
;


.global CURS_X: zp
.global CURS_Y: zp
.global SCREEN_PTR: zp
.global CHARCOLOR: zp
.global RVS: zp
.global BGCOLOR: zp
.global tickcount: zp
.global vdc_flags: zp
@@ -0,0 +1,18 @@
;
; Groepaz/Hitmen, 2015-11-19
;
; zeropage locations for exclusive use by the library
;

.include "extzp.inc"

.segment "EXTZP" : zeropage

CURS_X: .res 1
CURS_Y: .res 1
SCREEN_PTR: .res 2
CHARCOLOR: .res 1
RVS: .res 1
BGCOLOR: .res 1
tickcount: .res 4
vdc_flags: .res 1
@@ -0,0 +1,22 @@
;
; void gotoxy (unsigned char x, unsigned char y);
;

.export _gotoxy
.import popa, plot

.include "pce.inc"
.include "extzp.inc"

_gotoxy:
sta CURS_Y ; Set Y
jsr popa ; Get X
sta CURS_X ; Set X
jmp plot ; Set the cursor position

;-------------------------------------------------------------------------------
; force the init constructor to be imported

.import initconio
conio_init = initconio

@@ -0,0 +1,48 @@
;
; IRQ handling (PCE version)
;

.export initirq, doneirq, IRQStub

.import __INTERRUPTOR_COUNT__, callirq_y

.include "pce.inc"
.include "extzp.inc"

; ------------------------------------------------------------------------
.segment "INIT"

; a constructor
;
initirq:
rts

; ------------------------------------------------------------------------
.code

; a destructor
;
doneirq:
rts

; ------------------------------------------------------------------------

IRQStub:
phy

; Save the display-source flags (and, release the interrupt).
;
ldy a:VDC_CTRL
sty vdc_flags

ldy #<(__INTERRUPTOR_COUNT__ * 2)
beq @L1
phx
pha

jsr callirq_y

pla
plx
@L1: ply
rti
@@ -0,0 +1,159 @@

;
; Standard joystick driver for the PCEngine
;

.include "joy-kernel.inc"
.include "joy-error.inc"
.include "pce.inc"

.macpack module


; ------------------------------------------------------------------------
; Header. Includes jump table

module_header _pce_stdjoy_joy

; Driver signature

.byte $6A, $6F, $79 ; "joy"
.byte JOY_API_VERSION ; Driver API version number

; Library reference

.addr $0000

; Button state masks (8 values)

.byte $10 ; JOY_UP
.byte $40 ; JOY_DOWN
.byte $80 ; JOY_LEFT
.byte $20 ; JOY_RIGHT
.byte $01 ; JOY_FIRE_A
.byte $02 ; JOY_FIRE_B
.byte $04 ; JOY_SELECT
.byte $08 ; JOY_RUN

; Jump table.

.addr INSTALL
.addr UNINSTALL
.addr COUNT
.addr READJOY
.addr 0 ; IRQ entry unused

; ------------------------------------------------------------------------
; Constants

JOY_COUNT = 4 ; Number of joysticks we support


.code

; ------------------------------------------------------------------------
; INSTALL routine. Is called after the driver is loaded into memory. If
; possible, check if the hardware is present and determine the amount of
; memory available.
; Must return an JOY_ERR_xx code in a/x.
;

INSTALL:
lda #<JOY_ERR_OK
ldx #>JOY_ERR_OK

; rts ; Run into UNINSTALL instead

; ------------------------------------------------------------------------
; DEINSTALL routine. Is called before the driver is removed from memory.
; Can do cleanup or whatever. Must not return anything.
;

UNINSTALL:
rts


; ------------------------------------------------------------------------
; COUNT: Return the total number of available joysticks in a/x.
;
;unsigned char __fastcall__ joy_count (void);

COUNT:
lda #<JOY_COUNT
ldx #>JOY_COUNT
rts

; ------------------------------------------------------------------------
; READ: Read a particular joystick passed in A.
;
;unsigned char __fastcall__ joy_read (unsigned char joystick);

READJOY:
pha
jsr read_joy
pla
tax ; Joystick number into X

; return value from buffer

joy1:
lda padbuffer,x
ldx #0
rts

read_joy:
; reset multitap counter
lda #$01
sta JOY_CTRL
pha
pla
nop
nop

lda #$03
sta JOY_CTRL
pha
pla
nop
nop

cly
nextpad:
lda #$01
sta JOY_CTRL ; sel = 1
pha
pla
nop ; some delay is required
nop

lda JOY_CTRL
asl a
asl a
asl a
asl a
sta padbuffer, y ; store new value

stz JOY_CTRL
pha
pla

nop ; some delay is required
nop

lda JOY_CTRL
and #$0F
ora padbuffer, y ; second half of new value

eor #$FF
sta padbuffer, y ; store new value

iny
cpy #$05
bcc nextpad
rts

.bss

padbuffer:
.res 4

@@ -0,0 +1,14 @@
;
; Address of the static standard joystick driver
;
; Oliver Schmidt, 2012-11-01
;
; const void joy_static_stddrv[];
;

.export _joy_static_stddrv
.import _pce_stdjoy_joy

.rodata

_joy_static_stddrv := _pce_stdjoy_joy
@@ -0,0 +1,13 @@
;
; Name of the standard joystick driver
;
; Oliver Schmidt, 2012-11-01
;
; const char joy_stddrv[];
;

.export _joy_stddrv

.rodata

_joy_stddrv: .asciiz "pce-stdjoy.joy"
@@ -0,0 +1,39 @@

.export PLOT

.include "pce.inc"
.include "extzp.inc"

PLOT:
bcs @getpos

tya
;clc ; already cleared
adc _plotlo,x
sta SCREEN_PTR

lda _plothi,x
adc #0
sta SCREEN_PTR+1
@getpos:
ldx CURS_Y
ldy CURS_X
rts

.rodata

_plotlo:
.repeat screenrows,line
.byte <($0000+(line*$80))
.endrepeat

_plothi:
.repeat screenrows,line
.byte >($0000+(line*$80))
.endrepeat

;-------------------------------------------------------------------------------
; force the init constructor to be imported

.import initconio
conio_init = initconio
@@ -0,0 +1,8 @@
;
; Oliver Schmidt, 2013-05-31
;

.export joy_libref
.import _exit

joy_libref := _exit
@@ -0,0 +1,30 @@

.include "pce.inc"

.export psg_init

psg_init:
clx
stz PSG_GLOBAL_PAN ; Clear global balance

psg_clear_loop:
stx PSG_CHAN_SELECT ; Select channel
stz PSG_FREQ_LO ; Clear frequency LSB
stz PSG_FREQ_HI ; Clear frequency MSB
stz PSG_CHAN_CTRL ; Clear volume
stz PSG_CHAN_PAN ; Clear balance
stz PSG_NOISE ; Clear noise control
stz PSG_LFO_FREQ ; Clear LFO frequency
stz PSG_LFO_CTRL ; Clear LFO control

cly
psg_clear_waveform:
stz PSG_CHAN_DATA ; Clear waveform byte
iny
cpy #$20
bne psg_clear_waveform

inx
cpx #$06
bne psg_clear_loop
rts
@@ -0,0 +1,28 @@

.include "pce.inc"
.include "extzp.inc"

.export _revers

.proc _revers

ldx #$00 ; Assume revers off
tay ; Test onoff
beq L1 ; Jump if off
ldx #$80 ; Load on value
ldy #$00 ; Assume old value is zero
L1: lda RVS ; Load old value
stx RVS ; Set new value
beq L2 ; Jump if old value zero
iny ; Make old value = 1
L2: ldx #$00 ; Load high byte of result
tya ; Load low byte, set CC
rts

.endproc

;-------------------------------------------------------------------------------
; force the init constructor to be imported

.import initconio
conio_init = initconio
@@ -0,0 +1,18 @@
.interruptor ticktock, 24

.include "pce.inc"
.include "extzp.inc"

ticktock:
bbr5 vdc_flags,@s1 ; not vertical-blank interrupt

; Increment the system tick counter.
inc tickcount
bne @s1
inc tickcount+1
bne @s1
inc tickcount+2
bne @s1
inc tickcount+3

@s1: rts
@@ -0,0 +1,20 @@

.include "pce.inc"

.export vce_init

vce_init:
; Set CTA to zero
stz VCE_ADDR_LO
stz VCE_ADDR_HI
ldy #$01
vce_clear_bank:
ldx #$00
vce_clear_color:
stz VCE_DATA_LO ; Clear color (LSB)
stz VCE_DATA_HI ; Clear color (MSB)
dex
bne vce_clear_color
dey
bne vce_clear_bank
rts
@@ -0,0 +1,41 @@

.include "pce.inc"

; FIXME: implement selection of different video modes at runtime
HIRES = 1

.export vdc_init

vdc_init:
lda a:VDC_CTRL

VREG $00, $0000 ; MAWR
VREG $01, $0000 ; MARR
VREG $05, $0000 ; CR
VREG $06, $0000 ; RCR
VREG $07, $0000 ; BXR
VREG $08, $0000 ; BYR
VREG $09, $0070 ; MAWR
VREG $0C, $1702 ; CRTC - VSR
VREG $0D, $00DF ; CRTC - VDS
VREG $0E, $000C ; CRTC - VDE
VREG $0F, $0000 ; DCR

.if HIRES

VREG $0A, $0C02 ; CRTC - HSR
VREG $0B, $043C ; CRTC - HDS
lda #$06
sta VCE_CTRL

.else

VREG $0A, $0202 ; CRTC - HSR
VREG $0B, $041F ; CRTC - HDS
lda #$04
sta VCE_CTRL

.endif

lda a:VDC_CTRL
rts
@@ -0,0 +1,220 @@

; VGA charset for the PC-Engine conio implementation

.byte $00, $00, $00, $00, $00, $00, $00, $00

.byte %00000000
.byte %00000000
.byte %00000000
.byte %11111111
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000

.byte %00010000
.byte %00010000
.byte %00010000
.byte %00010000
.byte %00010000
.byte %00010000
.byte %00010000
.byte %00010000

.byte %00010000
.byte %00010000
.byte %00010000
.byte %11111111
.byte %00010000
.byte %00010000
.byte %00010000
.byte %00010000

.byte %00000000
.byte %00000000
.byte %00000000
.byte %00011111
.byte %00010000
.byte %00010000
.byte %00010000
.byte %00010000

.byte %00000000
.byte %00000000
.byte %00000000
.byte %11110000
.byte %00010000
.byte %00010000
.byte %00010000
.byte %00010000

.byte %00010000
.byte %00010000
.byte %00010000
.byte %00011111
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000

.byte %00010000
.byte %00010000
.byte %00010000
.byte %11110000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000

.byte %00000000
.byte %00000000
.byte %00000000
.byte %11111111
.byte %00010000
.byte %00010000
.byte %00010000
.byte %00010000

.byte %00010000
.byte %00010000
.byte %00010000
.byte %11111111
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000

.byte %00010000
.byte %00010000
.byte %00010000
.byte %00011111
.byte %00010000
.byte %00010000
.byte %00010000
.byte %00010000

.byte %00010000
.byte %00010000
.byte %00010000
.byte %11110000
.byte %00010000
.byte %00010000
.byte %00010000
.byte %00010000

.byte $3C, $66, $66, $66, $3C, $18, $7E, $18
.byte $3F, $33, $3F, $30, $30, $70, $F0, $E0
.byte $7F, $63, $7F, $63, $63, $67, $E6, $C0
.byte $99, $5A, $3C, $E7, $E7, $3C, $5A, $99
.byte $80, $E0, $F8, $FE, $F8, $E0, $80, $00
.byte $02, $0E, $3E, $FE, $3E, $0E, $02, $00
.byte $18, $3C, $7E, $18, $18, $7E, $3C, $18
.byte $66, $66, $66, $66, $66, $00, $66, $00
.byte $7F, $DB, $DB, $7B, $1B, $1B, $1B, $00
.byte $3E, $63, $38, $6C, $6C, $38, $CC, $78
.byte $00, $00, $00, $00, $7E, $7E, $7E, $00
.byte $18, $3C, $7E, $18, $7E, $3C, $18, $FF
.byte $18, $3C, $7E, $18, $18, $18, $18, $00
.byte $18, $18, $18, $18, $7E, $3C, $18, $00
.byte $00, $18, $0C, $FE, $0C, $18, $00, $00
.byte $00, $30, $60, $FE, $60, $30, $00, $00
.byte $00, $00, $C0, $C0, $C0, $FE, $00, $00
.byte $00, $24, $66, $FF, $66, $24, $00, $00
.byte $00, $18, $3C, $7E, $FF, $FF, $00, $00
.byte $00, $FF, $FF, $7E, $3C, $18, $00, $00
.byte $00, $00, $00, $00, $00, $00, $00, $00
.byte $30, $78, $78, $78, $30, $00, $30, $00
.byte $6C, $6C, $6C, $00, $00, $00, $00, $00
.byte $6C, $6C, $FE, $6C, $FE, $6C, $6C, $00
.byte $30, $7C, $C0, $78, $0C, $F8, $30, $00
.byte $00, $C6, $CC, $18, $30, $66, $C6, $00
.byte $38, $6C, $38, $76, $DC, $CC, $76, $00
.byte $60, $60, $C0, $00, $00, $00, $00, $00
.byte $18, $30, $60, $60, $60, $30, $18, $00
.byte $60, $30, $18, $18, $18, $30, $60, $00
.byte $00, $66, $3C, $FF, $3C, $66, $00, $00
.byte $00, $30, $30, $FC, $30, $30, $00, $00
.byte $00, $00, $00, $00, $00, $30, $30, $60
.byte $00, $00, $00, $FC, $00, $00, $00, $00
.byte $00, $00, $00, $00, $00, $30, $30, $00
.byte $06, $0C, $18, $30, $60, $C0, $80, $00
.byte $7C, $C6, $CE, $DE, $F6, $E6, $7C, $00
.byte $30, $70, $30, $30, $30, $30, $FC, $00
.byte $78, $CC, $0C, $38, $60, $CC, $FC, $00
.byte $78, $CC, $0C, $38, $0C, $CC, $78, $00
.byte $1C, $3C, $6C, $CC, $FE, $0C, $1E, $00
.byte $FC, $C0, $F8, $0C, $0C, $CC, $78, $00
.byte $38, $60, $C0, $F8, $CC, $CC, $78, $00
.byte $FC, $CC, $0C, $18, $30, $30, $30, $00
.byte $78, $CC, $CC, $78, $CC, $CC, $78, $00
.byte $78, $CC, $CC, $7C, $0C, $18, $70, $00
.byte $00, $30, $30, $00, $00, $30, $30, $00
.byte $00, $30, $30, $00, $00, $30, $30, $60
.byte $18, $30, $60, $C0, $60, $30, $18, $00
.byte $00, $00, $FC, $00, $00, $FC, $00, $00
.byte $60, $30, $18, $0C, $18, $30, $60, $00
.byte $78, $CC, $0C, $18, $30, $00, $30, $00
.byte $7C, $C6, $DE, $DE, $DE, $C0, $78, $00
.byte $30, $78, $CC, $CC, $FC, $CC, $CC, $00
.byte $FC, $66, $66, $7C, $66, $66, $FC, $00
.byte $3C, $66, $C0, $C0, $C0, $66, $3C, $00
.byte $F8, $6C, $66, $66, $66, $6C, $F8, $00
.byte $7E, $60, $60, $78, $60, $60, $7E, $00
.byte $7E, $60, $60, $78, $60, $60, $60, $00
.byte $3C, $66, $C0, $C0, $CE, $66, $3E, $00
.byte $CC, $CC, $CC, $FC, $CC, $CC, $CC, $00
.byte $78, $30, $30, $30, $30, $30, $78, $00
.byte $1E, $0C, $0C, $0C, $CC, $CC, $78, $00
.byte $E6, $66, $6C, $78, $6C, $66, $E6, $00
.byte $60, $60, $60, $60, $60, $60, $7E, $00
.byte $C6, $EE, $FE, $FE, $D6, $C6, $C6, $00
.byte $C6, $E6, $F6, $DE, $CE, $C6, $C6, $00
.byte $38, $6C, $C6, $C6, $C6, $6C, $38, $00
.byte $FC, $66, $66, $7C, $60, $60, $F0, $00
.byte $78, $CC, $CC, $CC, $DC, $78, $1C, $00
.byte $FC, $66, $66, $7C, $6C, $66, $E6, $00
.byte $78, $CC, $E0, $70, $1C, $CC, $78, $00
.byte $FC, $30, $30, $30, $30, $30, $30, $00
.byte $CC, $CC, $CC, $CC, $CC, $CC, $FC, $00
.byte $CC, $CC, $CC, $CC, $CC, $78, $30, $00
.byte $C6, $C6, $C6, $D6, $FE, $EE, $C6, $00
.byte $C6, $C6, $6C, $38, $38, $6C, $C6, $00
.byte $CC, $CC, $CC, $78, $30, $30, $78, $00
.byte $FE, $06, $0C, $18, $30, $60, $FE, $00
.byte $78, $60, $60, $60, $60, $60, $78, $00
.byte $C0, $60, $30, $18, $0C, $06, $02, $00
.byte $78, $18, $18, $18, $18, $18, $78, $00
.byte $10, $38, $6C, $C6, $00, $00, $00, $00
.byte $00, $00, $00, $00, $00, $00, $00, $FF
.byte $30, $30, $18, $00, $00, $00, $00, $00
.byte $00, $00, $78, $0C, $7C, $CC, $76, $00
.byte $E0, $60, $60, $7C, $66, $66, $DC, $00
.byte $00, $00, $78, $CC, $C0, $CC, $78, $00
.byte $1C, $0C, $0C, $7C, $CC, $CC, $76, $00
.byte $00, $00, $78, $CC, $FC, $C0, $78, $00
.byte $38, $6C, $60, $F0, $60, $60, $F0, $00
.byte $00, $00, $76, $CC, $CC, $7C, $0C, $F8
.byte $E0, $60, $6C, $76, $66, $66, $E6, $00
.byte $30, $00, $70, $30, $30, $30, $78, $00
.byte $0C, $00, $0C, $0C, $0C, $CC, $CC, $78
.byte $E0, $60, $66, $6C, $78, $6C, $E6, $00
.byte $70, $30, $30, $30, $30, $30, $78, $00
.byte $00, $00, $CC, $FE, $FE, $D6, $C6, $00
.byte $00, $00, $F8, $CC, $CC, $CC, $CC, $00
.byte $00, $00, $78, $CC, $CC, $CC, $78, $00
.byte $00, $00, $DC, $66, $66, $7C, $60, $F0
.byte $00, $00, $76, $CC, $CC, $7C, $0C, $1E
.byte $00, $00, $DC, $76, $66, $60, $F0, $00
.byte $00, $00, $7C, $C0, $78, $0C, $F8, $00
.byte $10, $30, $7C, $30, $30, $34, $18, $00
.byte $00, $00, $CC, $CC, $CC, $CC, $76, $00
.byte $00, $00, $CC, $CC, $CC, $78, $30, $00
.byte $00, $00, $C6, $D6, $FE, $FE, $6C, $00
.byte $00, $00, $C6, $6C, $38, $6C, $C6, $00
.byte $00, $00, $CC, $CC, $CC, $7C, $0C, $F8
.byte $00, $00, $FC, $98, $30, $64, $FC, $00
.byte $1C, $30, $30, $E0, $30, $30, $1C, $00
.byte $18, $18, $18, $00, $18, $18, $18, $00
.byte $E0, $30, $30, $1C, $30, $30, $E0, $00
.byte $76, $DC, $00, $00, $00, $00, $00, $00
.byte $00, $10, $38, $6C, $C6, $C6, $FE, $00
@@ -0,0 +1,18 @@
;
; void waitvblank (void);
;

.include "pce.inc"
.include "extzp.inc"

.forceimport ticktock
.export _waitvblank

.proc _waitvblank

lda tickcount
@lp: cmp tickcount
beq @lp
rts

.endproc
@@ -68,7 +68,7 @@ int main (void)
gotoxy ((XSize - strlen (Text)) / 2, YSize / 2);
cprintf ("%s", Text);

#if defined(__NES__)
#if defined(__NES__) || defined(__PCE__)

/* Wait for the user to press a button */
joy_install (joy_static_stddrv);
@@ -307,6 +307,10 @@ static void SetSys (const char* Sys)
NewSymbol ("__OSIC1P__", 1);
break;

case TGT_PCENGINE:
NewSymbol ("__PCE__", 1);
break;

default:
AbEnd ("Invalid target name: `%s'", Sys);

@@ -263,6 +263,10 @@ static void SetSys (const char* Sys)
DefineNumericMacro ("__OSIC1P__", 1);
break;

case TGT_PCENGINE:
DefineNumericMacro ("__PCE__", 1);
break;

default:
AbEnd ("Unknown target system type %d", Target);
}
@@ -163,6 +163,7 @@ static const TargetEntry TargetMap[] = {
{ "nes", TGT_NES },
{ "none", TGT_NONE },
{ "osic1p", TGT_OSIC1P },
{ "pce", TGT_PCENGINE },
{ "pet", TGT_PET },
{ "plus4", TGT_PLUS4 },
{ "sim6502", TGT_SIM6502 },
@@ -202,6 +203,7 @@ static const TargetProperties PropertyTable[TGT_COUNT] = {
{ "lynx", CPU_65C02, BINFMT_BINARY, CTNone },
{ "sim6502", CPU_6502, BINFMT_BINARY, CTNone },
{ "sim65c02", CPU_65C02, BINFMT_BINARY, CTNone },
{ "pce", CPU_HUC6280, BINFMT_BINARY, CTNone },
};

/* Target system */
@@ -78,6 +78,7 @@ typedef enum {
TGT_LYNX,
TGT_SIM6502,
TGT_SIM65C02,
TGT_PCENGINE,
TGT_COUNT /* Number of target systems */
} target_t;

@@ -0,0 +1,13 @@

all: conio.pce

conio.pce: conio.c
../../../bin/cl65 -t pce conio.c --mapfile conio.map -o conio.pce

clean:
$(RM) conio.pce
$(RM) conio.map

test: conio.pce
mednafen -force_module pce conio.pce

@@ -0,0 +1,121 @@

#include <conio.h>
#include <time.h>
#include <joystick.h>
#include <string.h>
#include <stdlib.h>

static int datavar = 10;

void main(void)
{
int stackvar = 42;
int i, j;
clock_t clk;
char* p;
unsigned char xsize, ysize, n;

joy_install(&joy_static_stddrv);

clrscr();
screensize(&xsize, &ysize);

cputs("hello world");
cputsxy(0, 2, "colors:" );
for (i = 0; i < 16; ++i) {
textcolor(i);
cputc('X');
}
textcolor(1);

gotoxy(0,4);
cprintf("datavar: %02x\n\r", datavar);
cprintf("stackvar: %02x\n\r", stackvar);

j = joy_count();
gotoxy(0,9);
cprintf("Found %d Joysticks.", j);

for (i = 0; i < 4; ++i) {
gotoxy(0, 16 + i);
p = malloc(16);
memcpy(p, "0123456789abcdef", 16);
cprintf("alloced at: %04p - %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", p,
p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],
p[8],p[9],p[10],p[11],p[12],p[13],p[14],p[15]
);
}

gotoxy(0,ysize - 1);
for (i = 0; i < xsize; ++i) {
cputc('0' + i % 10);
}

gotoxy(0,ysize - 2 - ((256 + xsize) / xsize));
for (i = 0; i < xsize; ++i) {
cputc('0' + i % 10);
}
for (i = 0; i < (xsize * 5); ++i) {
cputc('#');
}
gotoxy(0,ysize - 1 - ((256 + xsize) / xsize));
for (i = 0; i < 256; ++i) {
if ((i != '\n') && (i != '\r')) {
cputc(i);
}
}

i = get_tv();
gotoxy(30,0);
cputs("TV Mode: ");
switch(i) {
case TV_NTSC:
cputs("NTSC");
break;
case TV_PAL:
cputs("PAL");
break;
case TV_OTHER:
cputs("OTHER");
break;
}
cprintf(" %dx%d", xsize, ysize);

for(;;) {
gotoxy(13,4);
cprintf("%02x", datavar);
gotoxy(13,5);
cprintf("%02x", stackvar);
++datavar; ++stackvar;

gotoxy(0,7);
clk = clock();
cprintf("clock: %08lx", clk);

for (i = 0; i < 4; ++i) {
gotoxy(0, 11 + i);
j = joy_read (i);
cprintf ("pad %d: %02x %-6s%-6s%-6s%-6s%-6s%-6s%-6s%-6s",
i, j,
(j & joy_masks[JOY_UP])? " up " : " ---- ",
(j & joy_masks[JOY_DOWN])? " down " : " ---- ",
(j & joy_masks[JOY_LEFT])? " left " : " ---- ",
(j & joy_masks[JOY_RIGHT])? "right " : " ---- ",
(j & joy_masks[JOY_FIRE])? " fire " : " ---- ",
(j & joy_masks[JOY_FIRE2])? "fire2 " : " ---- ",
(j & joy_masks[JOY_SELECT])? "select" : " ---- ",
(j & joy_masks[JOY_RUN])? " run " : " ---- ");
}

gotoxy(xsize - 10, 3);
j = (n >> 5) & 1;
revers(j);
cputc(j ? 'R' : ' ');
cputs(" revers");
revers(0);

waitvblank();
++n;
}
for(;;);
}