Setting up new repository with just the JoeyLib code in it.
This commit is contained in:
commit
21b2306e9b
16 changed files with 3097 additions and 0 deletions
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
*.sta filter=lfs diff=lfs merge=lfs -text
|
||||
*.mod filter=lfs diff=lfs merge=lfs -text
|
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
*~
|
||||
*.user
|
||||
lib/
|
||||
src/SDL2/
|
||||
src/music
|
||||
src/music.w
|
||||
src/*.dis
|
50
build-IIgs.sh
Executable file
50
build-IIgs.sh
Executable file
|
@ -0,0 +1,50 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
if [ -d ${JOEY}/sdks/iix/IIgs/out/joey ]; then
|
||||
rm -rf ${JOEY}/sdks/iix/IIgs/out/joey
|
||||
fi
|
||||
mkdir -p ${JOEY}/sdks/iix/IIgs/out/joey
|
||||
|
||||
pushd ${JOEY}/joeylib/src
|
||||
iix assemble jIIgs.asm keep=31:/out/joey/jIIgsasm
|
||||
iix compile jIIgs.c keep=31:/out/joey/jIIgsc
|
||||
iix compile joey.c keep=31:/out/joey/joey
|
||||
|
||||
iix makelib 31:/out/joey/joeylib +31:/out/joey/jIIgsasm.A
|
||||
iix makelib 31:/out/joey/joeylib +31:/out/joey/jIIgsasm.ROOT
|
||||
iix makelib 31:/out/joey/joeylib +31:/out/joey/jIIgsc.a
|
||||
iix makelib 31:/out/joey/joeylib +31:/out/joey/joey.a
|
||||
|
||||
iix compile test.c keep=31:/out/joey/test
|
||||
iix -DKeepType=S16 link 31:/out/joey/test 31:/out/joey/joeylib keep=31:/out/joey/test
|
||||
|
||||
iix dumpobj +D 31:/out/joey/test &> test.dis || true
|
||||
|
||||
php ${JOEY}/sdks/iix/ntconverter.php *.mod
|
||||
popd
|
||||
|
||||
rm JLSTATS || true
|
||||
rm /tmp/import.po || true
|
||||
|
||||
AC=${JOEY}/sdks/iix/ac/
|
||||
CADIUS=${JOEY}/sdks/iix/cadius/cadius.sh
|
||||
IMPORT=/tmp/import.po
|
||||
|
||||
${AC}/import.sh ${JOEY}/sdks/iix/IIgs/out/joey/test S16
|
||||
${AC}/import.sh ${JOEY}/joeylib/src/kanga.sta
|
||||
${AC}/import.sh ${JOEY}/joeylib/src/font.sta
|
||||
${AC}/import.sh ${JOEY}/joeylib/src/music MUS
|
||||
${AC}/import.sh ${JOEY}/joeylib/src/music.w BIN
|
||||
|
||||
cp -f ${JOEY}/joeylib/lib/IIgs/Tool221#ba0000 ${JOEY}/dist/IIgs/.
|
||||
cp -f ${JOEY}/joeylib/src/joey.h ${JOEY}/dist/.
|
||||
cp -f ${JOEY}/sdks/iix/IIgs/out/joey/joeylib ${JOEY}/dist/IIgs/joeylib#b20000
|
||||
|
||||
if [ ! -z $1 ]; then
|
||||
pushd ${JOEY}/sdks/iix/gsplus
|
||||
./gsplus -config IIgsTest.cfg || true
|
||||
popd
|
||||
echo ""
|
||||
${AC}/export.sh JLSTATS
|
||||
cat JLSTATS
|
||||
fi
|
69
build-PC.sh
Executable file
69
build-PC.sh
Executable file
|
@ -0,0 +1,69 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
|
||||
BUILD="${JOEY}/joeylib/build"
|
||||
SRC="${JOEY}/joeylib/src"
|
||||
|
||||
|
||||
function doBuild() {
|
||||
if [ -d "${BUILD}" ]; then
|
||||
rm -rf "${BUILD}"
|
||||
fi
|
||||
mkdir -p "${BUILD}"
|
||||
if [ -d "${DIST}" ]; then
|
||||
rm -rf "${DIST}"
|
||||
fi
|
||||
mkdir -p "${DIST}"
|
||||
|
||||
pushd "${BUILD}"
|
||||
${CC} ${CFLAGS} -c -o jPC.o ${SRC}/jPC.c
|
||||
${CC} ${CFLAGS} -c -o joey.o ${SRC}/joey.c
|
||||
cp -f *.o "${DIST}"/.
|
||||
popd
|
||||
|
||||
pushd ${DIST}
|
||||
ar -x ${INSTALLED}/libSDL2.a
|
||||
ar -x ${INSTALLED}/libSDL2_mixer.a
|
||||
ar -x ${INSTALLED}/libmikmod.a
|
||||
ar rcs joeylib.a *.o
|
||||
rm *.o
|
||||
popd
|
||||
}
|
||||
|
||||
CC="gcc"
|
||||
CFLAGS="-Wall -D_REENTRANT -I${SRC}"
|
||||
DIST="${JOEY}/dist/linux/x64"
|
||||
INSTALLED="${JOEY}/SDL2/installed/linux/x64/lib"
|
||||
doBuild
|
||||
|
||||
CC="gcc"
|
||||
CFLAGS="-m32 -Wall -D_REENTRANT -I${SRC}"
|
||||
DIST="${JOEY}/dist/linux/x86"
|
||||
INSTALLED="${JOEY}/SDL2/installed/linux/x86/lib"
|
||||
doBuild
|
||||
|
||||
CC="x86_64-w64-mingw32-gcc"
|
||||
CFLAGS="-Wall -D_REENTRANT -I${SRC}"
|
||||
DIST="${JOEY}/dist/windows/x64"
|
||||
INSTALLED="${JOEY}/SDL2/installed/windows/x64/lib"
|
||||
doBuild
|
||||
|
||||
CC="i686-w64-mingw32-gcc"
|
||||
CFLAGS="-Wall -D_REENTRANT -I${SRC}"
|
||||
DIST="${JOEY}/dist/windows/x86"
|
||||
INSTALLED="${JOEY}/SDL2/installed/windows/x86/lib"
|
||||
doBuild
|
||||
|
||||
CC="o32-clang"
|
||||
CFLAGS="-Wall -D_REENTRANT -I${SRC}"
|
||||
DIST="${JOEY}/dist/macos/x86"
|
||||
INSTALLED="${JOEY}/SDL2/installed/macos/x86/lib"
|
||||
doBuild
|
||||
|
||||
CC="o64-clang"
|
||||
CFLAGS="-Wall -D_REENTRANT -I${SRC}"
|
||||
DIST="${JOEY}/dist/macos/x64"
|
||||
INSTALLED="${JOEY}/SDL2/installed/macos/x64/lib"
|
||||
doBuild
|
||||
|
||||
rm -rf build
|
45
joeylib.pro
Normal file
45
joeylib.pro
Normal file
|
@ -0,0 +1,45 @@
|
|||
TEMPLATE = app
|
||||
CONFIG += console
|
||||
CONFIG -= \
|
||||
app_bundle \
|
||||
qt
|
||||
|
||||
QMAKE_CFLAGS += \
|
||||
-I$$PWD/src \
|
||||
-D_REENTRANT
|
||||
|
||||
HEADERS += \
|
||||
src/joey.h \
|
||||
src/stddclmr.h
|
||||
|
||||
SOURCES += \
|
||||
src/joey.c \
|
||||
src/jPC.c \
|
||||
src/test.c
|
||||
|
||||
OTHER_FILES += \
|
||||
src/jIIgs.c \
|
||||
src/jIIgs.asm \
|
||||
src/jIIgs.macro \
|
||||
build-IIgs.sh \
|
||||
build-PC.sh
|
||||
|
||||
SDL_LIBS = \
|
||||
-L$$PWD/lib/linux/x64 \
|
||||
-Wl,-rpath,$$PWD/lib/linux/x64 \
|
||||
-Wl,--enable-new-dtags \
|
||||
-lSDL2 \
|
||||
-Wl,--no-undefined \
|
||||
-lm \
|
||||
-ldl \
|
||||
-lpthread \
|
||||
-lrt
|
||||
|
||||
SDL_MIXER_LIBS = \
|
||||
-L$$PWD/lib/linux/x64 \
|
||||
-lSDL2_mixer \
|
||||
-lmikmod
|
||||
|
||||
LIBS += \
|
||||
$$SDL_LIBS \
|
||||
$$SDL_MIXER_LIBS
|
BIN
src/font.sta
Normal file
BIN
src/font.sta
Normal file
Binary file not shown.
721
src/jIIgs.asm
Normal file
721
src/jIIgs.asm
Normal file
|
@ -0,0 +1,721 @@
|
|||
;----------------------------------------
|
||||
; JoeyLib
|
||||
; Copyright (C) 2018 Scott Duensing <scott@kangaroopunch.com>
|
||||
;
|
||||
; This software is provided 'as-is', without any express 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.
|
||||
;----------------------------------------
|
||||
|
||||
mcopy 13:ORCAInclude:m16.ORCA
|
||||
mcopy jIIgs.macro
|
||||
case on
|
||||
|
||||
SHRShad gequ $012000
|
||||
|
||||
savedDBR data ; Storage for Data Bank Register
|
||||
ds 2 ; 16 bits
|
||||
end ; Used by jIIgs.macro
|
||||
|
||||
vblDBR data ; Storage for Data Bank Register during VBL Interrupt
|
||||
ds 2 ; 16 bits
|
||||
end
|
||||
|
||||
ScanTable data
|
||||
ds 400 ; 400 bytes for scanline offsets
|
||||
end
|
||||
|
||||
VblRate data
|
||||
ds 2 ; Either 5 or 6 depending on PAL or NTSC.
|
||||
VblTime ds 2 ; Integer Counter
|
||||
end
|
||||
|
||||
;----------------------------------------
|
||||
; Blit an 8x8 block from off-screen to back buffer.
|
||||
;----------------------------------------
|
||||
asmB88 start
|
||||
|
||||
t equ 1
|
||||
|
||||
jsubroutine (4:p,2:cx1,2:cy1,2:cx2,2:cy2),2
|
||||
using ScanTable
|
||||
|
||||
phb ; Push our current data bank onto the stack
|
||||
|
||||
; Find offset into tile memory
|
||||
clc
|
||||
lda cx1 ; Multiply cx1 by 4 to get offset (two pixels per byte)
|
||||
asl a
|
||||
asl a
|
||||
sta t
|
||||
clc
|
||||
lda cy1 ; Multiply cy1 by 16 to get index into scanline table
|
||||
asl a
|
||||
asl a
|
||||
asl a
|
||||
asl a ; y1 is now in the accumulator
|
||||
clc
|
||||
tax
|
||||
lda >ScanTable,x
|
||||
adc t ; Add t to scanline offset
|
||||
tay ; Offset to start of tile
|
||||
; Find offset into shadow SHR memory
|
||||
clc
|
||||
lda cx2 ; Multiply cx1 by 4 to get offset (two pixels per byte)
|
||||
asl a
|
||||
asl a
|
||||
sta t
|
||||
clc
|
||||
lda cy2 ; Multiply cy1 by 16 to get index into scanline table
|
||||
asl a
|
||||
asl a
|
||||
asl a
|
||||
asl a ; y2 is now in the accumulator
|
||||
clc
|
||||
tax
|
||||
lda >ScanTable,x
|
||||
adc t ; Add t to scanline offset
|
||||
tax ; Offset to start of screen memory
|
||||
|
||||
sei ; Disable interrupts while we change data banks
|
||||
pea $0101 ; Push Effective Address (our new data bank) always 16 bits
|
||||
plb ; Pull data bank from stack (data bank now $01)
|
||||
plb ; Do it twice because it's only an 8 bit operation
|
||||
|
||||
; Row 1
|
||||
lda [p],y ; Load 4 pixels from SHA data
|
||||
sta |SHRShad,x ; Store 4 pixels into screen
|
||||
inx ; Move to next pixel quad
|
||||
inx
|
||||
iny
|
||||
iny
|
||||
lda [p],y ; Load 4 pixels from SHA data
|
||||
sta |SHRShad,x ; Store 4 pixels into screen
|
||||
; Move to row 2
|
||||
txa
|
||||
adc #158 ; Next line
|
||||
tax
|
||||
tya
|
||||
adc #158 ; Next line
|
||||
tay
|
||||
; Row 2
|
||||
lda [p],y ; Load 4 pixels from SHA data
|
||||
sta |SHRShad,x ; Store 4 pixels into screen
|
||||
inx ; Move to next pixel quad
|
||||
inx
|
||||
iny
|
||||
iny
|
||||
lda [p],y ; Load 4 pixels from SHA data
|
||||
sta |SHRShad,x ; Store 4 pixels into screen
|
||||
; Move to row 3
|
||||
txa
|
||||
adc #158 ; Next line
|
||||
tax
|
||||
tya
|
||||
adc #158 ; Next line
|
||||
tay
|
||||
; Row 3
|
||||
lda [p],y ; Load 4 pixels from SHA data
|
||||
sta |SHRShad,x ; Store 4 pixels into screen
|
||||
inx ; Move to next pixel quad
|
||||
inx
|
||||
iny
|
||||
iny
|
||||
lda [p],y ; Load 4 pixels from SHA data
|
||||
sta |SHRShad,x ; Store 4 pixels into screen
|
||||
; Move to row 4
|
||||
txa
|
||||
adc #158 ; Next line
|
||||
tax
|
||||
tya
|
||||
adc #158 ; Next line
|
||||
tay
|
||||
; Row 4
|
||||
lda [p],y ; Load 4 pixels from SHA data
|
||||
sta |SHRShad,x ; Store 4 pixels into screen
|
||||
inx ; Move to next pixel quad
|
||||
inx
|
||||
iny
|
||||
iny
|
||||
lda [p],y ; Load 4 pixels from SHA data
|
||||
sta |SHRShad,x ; Store 4 pixels into screen
|
||||
; Move to row 5
|
||||
txa
|
||||
adc #158 ; Next line
|
||||
tax
|
||||
tya
|
||||
adc #158 ; Next line
|
||||
tay
|
||||
; Row 5
|
||||
lda [p],y ; Load 4 pixels from SHA data
|
||||
sta |SHRShad,x ; Store 4 pixels into screen
|
||||
inx ; Move to next pixel quad
|
||||
inx
|
||||
iny
|
||||
iny
|
||||
lda [p],y ; Load 4 pixels from SHA data
|
||||
sta |SHRShad,x ; Store 4 pixels into screen
|
||||
; Move to row 6
|
||||
txa
|
||||
adc #158 ; Next line
|
||||
tax
|
||||
tya
|
||||
adc #158 ; Next line
|
||||
tay
|
||||
; Row 6
|
||||
lda [p],y ; Load 4 pixels from SHA data
|
||||
sta |SHRShad,x ; Store 4 pixels into screen
|
||||
inx ; Move to next pixel quad
|
||||
inx
|
||||
iny
|
||||
iny
|
||||
lda [p],y ; Load 4 pixels from SHA data
|
||||
sta |SHRShad,x ; Store 4 pixels into screen
|
||||
; Move to row 7
|
||||
txa
|
||||
adc #158 ; Next line
|
||||
tax
|
||||
tya
|
||||
adc #158 ; Next line
|
||||
tay
|
||||
; Row 7
|
||||
lda [p],y ; Load 4 pixels from SHA data
|
||||
sta |SHRShad,x ; Store 4 pixels into screen
|
||||
inx ; Move to next pixel quad
|
||||
inx
|
||||
iny
|
||||
iny
|
||||
lda [p],y ; Load 4 pixels from SHA data
|
||||
sta |SHRShad,x ; Store 4 pixels into screen
|
||||
; Move to row 8
|
||||
txa
|
||||
adc #158 ; Next line
|
||||
tax
|
||||
tya
|
||||
adc #158 ; Next line
|
||||
tay
|
||||
; Row 8
|
||||
lda [p],y ; Load 4 pixels from SHA data
|
||||
sta |SHRShad,x ; Store 4 pixels into screen
|
||||
inx ; Move to next pixel quad
|
||||
inx
|
||||
iny
|
||||
iny
|
||||
lda [p],y ; Load 4 pixels from SHA data
|
||||
sta |SHRShad,x ; Store 4 pixels into screen
|
||||
|
||||
plb ; Pull original data bank from stack
|
||||
cli ; Restore interrupts
|
||||
|
||||
jreturn
|
||||
end
|
||||
|
||||
;----------------------------------------
|
||||
; Set Border Color
|
||||
;----------------------------------------
|
||||
asmBorder start
|
||||
jsubroutine (2:c)
|
||||
short m
|
||||
lda $E0C034
|
||||
and #$F0
|
||||
ora c
|
||||
sta $E0C034
|
||||
long m
|
||||
jreturn
|
||||
end
|
||||
|
||||
;----------------------------------------
|
||||
; Returns the color of a given point
|
||||
;
|
||||
; Psychotically commented to help learn ASM :-)
|
||||
;----------------------------------------
|
||||
asmGetPoint start
|
||||
|
||||
temp1 equ 1
|
||||
|
||||
jsubroutine (2:Xp,2:Yp),2
|
||||
using ScanTable
|
||||
|
||||
lda Yp ; Load accumulator with Y location
|
||||
asl a ; Shift accumulator left (multiply by 2) for word offset into table
|
||||
tax ; Transfer accumulator to x register
|
||||
lda >ScanTable,x ; Look up scan line address offset
|
||||
sta temp1 ; Store accumulator (row offset into SHR memory) into temp1
|
||||
clc ; Clear carry flag
|
||||
lda Xp ; Place X position in accumulator
|
||||
lsr a ; Logical Shift Right (divide by 2, two pixels per byte) - bit shifted off the end goes into carry flag
|
||||
php ; Save our carry flag for later!
|
||||
clc ; Clear carry
|
||||
adc temp1 ; Add X position to SHR address with carry - a now contains address of color pair we want
|
||||
plp ; Restore our carry flag
|
||||
tax ; Transfer accumulator to x register
|
||||
lda SHRShad,x ; Load pixel pair into accumulator
|
||||
bcc GEven ; Branch if Carry Clear - Determines Even/Odd pixel
|
||||
and #$F ; AND accumulator with $F to mask off unwanted pixel
|
||||
bra GBoth
|
||||
|
||||
GEven and #$F0 ; AND accumulator with $F0 to mask off unwanted pixel
|
||||
lsr a ; Shift the result down a nibble
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
|
||||
GBoth sta temp1 ; Store accumulator in temp1
|
||||
|
||||
jreturn 2:temp1
|
||||
end
|
||||
|
||||
;----------------------------------------
|
||||
; Return the current 1/10th second timer value
|
||||
;----------------------------------------
|
||||
asmGetVbl start
|
||||
using VblRate
|
||||
lda >VblTime
|
||||
rtl
|
||||
end
|
||||
|
||||
;----------------------------------------
|
||||
; Turns off SHR Graphics
|
||||
;----------------------------------------
|
||||
asmGrOff start
|
||||
jsubroutine
|
||||
short m
|
||||
lda $E1C029
|
||||
and #$7F
|
||||
sta $E1C029
|
||||
long m
|
||||
jreturn
|
||||
end
|
||||
|
||||
;----------------------------------------
|
||||
; Turns on SHR Graphics
|
||||
;----------------------------------------
|
||||
asmGrOn start
|
||||
jsubroutine
|
||||
short m
|
||||
lda $E1C029
|
||||
ora #$C1
|
||||
sta $E1C029
|
||||
long m
|
||||
jreturn
|
||||
end
|
||||
|
||||
;----------------------------------------
|
||||
; Reads controller axis
|
||||
;----------------------------------------
|
||||
asmJoy start
|
||||
|
||||
count equ 1
|
||||
|
||||
strobe equ $00C070 ; Paddle timer reset
|
||||
paddle equ $00C064 ; First paddle address
|
||||
|
||||
jsubroutine (2:which),2
|
||||
|
||||
lda which ; Which paddle/axis do we want?
|
||||
tax
|
||||
php
|
||||
sei ; Disable interrupts
|
||||
stz count ; Reset paddle value counter
|
||||
short m
|
||||
lda >strobe ; Start timer
|
||||
pdlLbl1 nop ; Delay some
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
inc count ; Increment paddle value counter
|
||||
beq pdlLbl2 ; If we loop back to zero, Z is set and we branch
|
||||
lda >paddle,x ; Check paddle value
|
||||
bmi pdlLbl1 ; High bit not set yet
|
||||
pdlLbl2 dec count ; Decrement one. Makes timeouts equal 255.
|
||||
long m
|
||||
plp ; Restore interrupt setting
|
||||
|
||||
jreturn 2:count
|
||||
end
|
||||
|
||||
;----------------------------------------
|
||||
; Plots a point in a given color
|
||||
;
|
||||
; Psychotically commented to help learn ASM :-)
|
||||
;----------------------------------------
|
||||
asmPoint start
|
||||
|
||||
temp1 equ 1
|
||||
temp2 equ 3
|
||||
temp3 equ 5
|
||||
|
||||
jsubroutine (2:C,2:Xp,2:Yp),6
|
||||
using ScanTable
|
||||
|
||||
lda Xp ; Place X position in accumulator
|
||||
lsr a ; Logical Shift Right (divide by 2) - bit shifted off the end goes into carry flag
|
||||
sta temp1 ; Store accumulator in temp1
|
||||
bcc PEven ; Branch if Carry Clear - Determines Even/Odd pixel
|
||||
|
||||
POdd lda #$FFF0 ; Load accumulator with pixel mask
|
||||
sta temp2 ; Store accumulator in temp2
|
||||
lda C ; Load accumulator with color
|
||||
and #$F ; AND accumulator with $F
|
||||
bra PBoth ; Branch Always to PBoth
|
||||
|
||||
PEven lda #$FF0F ; Load accumulator with pixel mask
|
||||
sta temp2 ; Store accumulator in temp2
|
||||
lda C ; Load accumulator with color
|
||||
and #$F0 ; AND accumulator with $F0
|
||||
|
||||
PBoth sta temp3 ; Store accumulator in temp3
|
||||
lda Yp ; Load accumulator with Y location
|
||||
asl a ; Shift accumulator left (multiply by 2)
|
||||
tax ; Transfer accumulator to x register
|
||||
lda >ScanTable,x ; Look up scan line address offset
|
||||
adc temp1 ; Add X position to address with carry
|
||||
tax ; Transfer accumulator to x
|
||||
|
||||
lda SHRShad,x ; Load existing pixels into accumulator
|
||||
and temp2 ; AND accumulator with temp2
|
||||
ora temp3 ; OR accumulator with temp3
|
||||
sta SHRShad,x ; Store updated pixels back into memory
|
||||
|
||||
jreturn
|
||||
end
|
||||
|
||||
;----------------------------------------
|
||||
; Turn SHR Shadowing Off
|
||||
;----------------------------------------
|
||||
asmShOff start
|
||||
jsubroutine
|
||||
short m
|
||||
lda $E0C035
|
||||
ora #$08
|
||||
sta $E0C035
|
||||
long m
|
||||
jreturn
|
||||
end
|
||||
|
||||
;----------------------------------------
|
||||
; Turn SHR Shadowing On
|
||||
;----------------------------------------
|
||||
asmShOn start
|
||||
jsubroutine
|
||||
short m
|
||||
lda $E0C035
|
||||
and #$F7
|
||||
sta $E0C035
|
||||
long m
|
||||
jreturn
|
||||
end
|
||||
|
||||
;----------------------------------------
|
||||
; "PEI Slam" shadowed SHR display to the
|
||||
; actual display. Copies all 200 lines,
|
||||
; the palette, and SCBs.
|
||||
;
|
||||
; Basically stolen from https://www.yumpu.com/en/document/view/23761498/code-secrets-of-wolfenstein-3d-iigs-kansasfest
|
||||
;----------------------------------------
|
||||
asmSlam start
|
||||
|
||||
jsubroutine
|
||||
|
||||
php ; Push Processor Status Register
|
||||
tdc ; Transfer Direct Register to C Accumulator
|
||||
sta >DataPtr ; Store Accumulator in DataPtr
|
||||
tsc ; Transfer Stack Pointer to C Accumulator
|
||||
sta >StackPtr ; Store Accumulator in StackPtr
|
||||
|
||||
sei ; Disable interrupts
|
||||
short m
|
||||
sta >$00C005 ; Switch to AUX
|
||||
sta >$00C003
|
||||
long m
|
||||
|
||||
ldy #$2000 ; Point to start of SHR
|
||||
|
||||
peiChunk ldx #7 ; Chunks before interrupts
|
||||
|
||||
peiPage tya
|
||||
tcd ; Move DP
|
||||
|
||||
clc
|
||||
adc #$FF ; Point to top of page
|
||||
tcs ; Move stack
|
||||
|
||||
inc a
|
||||
tay ; Keep + 0x100 for later
|
||||
|
||||
pei $FE ; "Slam" a single page
|
||||
pei $FC
|
||||
pei $FA
|
||||
pei $F8
|
||||
pei $F6
|
||||
pei $F4
|
||||
pei $F2
|
||||
pei $F0
|
||||
pei $EE
|
||||
pei $EC
|
||||
pei $EA
|
||||
pei $E8
|
||||
pei $E6
|
||||
nop
|
||||
pei $E4
|
||||
pei $E2
|
||||
pei $E0
|
||||
pei $DE
|
||||
pei $DC
|
||||
pei $DA
|
||||
pei $D8
|
||||
pei $D6
|
||||
pei $D4
|
||||
pei $D2
|
||||
pei $D0
|
||||
pei $CE
|
||||
pei $CC
|
||||
nop
|
||||
pei $CA
|
||||
pei $C8
|
||||
pei $C6
|
||||
pei $C4
|
||||
pei $C2
|
||||
pei $C0
|
||||
pei $BE
|
||||
pei $BC
|
||||
pei $BA
|
||||
pei $B8
|
||||
pei $B6
|
||||
pei $B4
|
||||
pei $B2
|
||||
nop
|
||||
pei $B0
|
||||
pei $AE
|
||||
pei $AC
|
||||
pei $AA
|
||||
pei $A8
|
||||
pei $A6
|
||||
pei $A4
|
||||
pei $A2
|
||||
pei $A0
|
||||
pei $9E
|
||||
pei $9C
|
||||
pei $9A
|
||||
pei $98
|
||||
nop
|
||||
pei $96
|
||||
pei $94
|
||||
pei $92
|
||||
pei $90
|
||||
pei $8E
|
||||
pei $8C
|
||||
pei $8A
|
||||
pei $88
|
||||
pei $86
|
||||
pei $84
|
||||
pei $82
|
||||
pei $80
|
||||
nop
|
||||
pei $7E
|
||||
pei $7C
|
||||
pei $7A
|
||||
pei $78
|
||||
pei $76
|
||||
pei $74
|
||||
pei $72
|
||||
pei $70
|
||||
pei $6E
|
||||
pei $6C
|
||||
pei $6A
|
||||
pei $68
|
||||
pei $66
|
||||
nop
|
||||
pei $64
|
||||
pei $62
|
||||
pei $60
|
||||
pei $5E
|
||||
pei $5C
|
||||
pei $5A
|
||||
pei $58
|
||||
pei $56
|
||||
pei $54
|
||||
pei $52
|
||||
pei $50
|
||||
pei $4E
|
||||
nop
|
||||
pei $4C
|
||||
pei $4A
|
||||
pei $48
|
||||
pei $46
|
||||
pei $44
|
||||
pei $42
|
||||
pei $40
|
||||
pei $3E
|
||||
pei $3C
|
||||
pei $3A
|
||||
pei $38
|
||||
pei $36
|
||||
pei $34
|
||||
nop
|
||||
pei $32
|
||||
pei $30
|
||||
pei $2E
|
||||
pei $2C
|
||||
pei $2A
|
||||
pei $28
|
||||
pei $26
|
||||
pei $24
|
||||
pei $22
|
||||
pei $20
|
||||
pei $1E
|
||||
pei $1C
|
||||
pei $1A
|
||||
nop
|
||||
pei $18
|
||||
pei $16
|
||||
pei $14
|
||||
pei $12
|
||||
pei $10
|
||||
pei $0E
|
||||
pei $0C
|
||||
pei $0A
|
||||
pei $08
|
||||
pei $06
|
||||
pei $04
|
||||
pei $02
|
||||
pei $00
|
||||
|
||||
cpy #$A000 ; Did we copy everything?
|
||||
bge peiEnd ; Yep!
|
||||
|
||||
dex
|
||||
bmi peiInts ; Do we need to process interrupts?
|
||||
|
||||
brl peiPage
|
||||
|
||||
peiInts short m
|
||||
sta >$00C004 ; Switch to MAIN
|
||||
sta >$00C002
|
||||
long m
|
||||
lda >StackPtr ; Load original Stack Pointer into Accumulator
|
||||
tcs ; Transfer Accumulator to Stack Pointer (Restores original stack)
|
||||
lda >DataPtr ; Load original Direct Pointer into Accumulator
|
||||
tcd ; Transfer Accumulator to Direct Pointer (Restores direct page)
|
||||
|
||||
cli ; Go Interrupts! Go!
|
||||
sei ; Stop interrupts
|
||||
|
||||
short m
|
||||
sta >$00C005 ; Switch to AUX
|
||||
sta >$00C003
|
||||
long m
|
||||
|
||||
brl peiChunk
|
||||
|
||||
peiEnd short m
|
||||
sta >$00C004 ; Switch to MAIN
|
||||
sta >$00C002
|
||||
long m
|
||||
lda >StackPtr
|
||||
tcs ; Restore stack
|
||||
lda >DataPtr
|
||||
tcd ; Restore DP
|
||||
cli ; Enable Interrupts
|
||||
|
||||
plp ; Restore processor register
|
||||
|
||||
jreturn
|
||||
|
||||
StackPtr ds 2 ; Space for SP
|
||||
DataPtr ds 2 ; Space for DP
|
||||
|
||||
end
|
||||
|
||||
;----------------------------------------
|
||||
; Start up assembly routines
|
||||
;
|
||||
; Builds a table of scanline offsets
|
||||
;----------------------------------------
|
||||
asmStart start
|
||||
jsubroutine (2:id,2:h)
|
||||
using ScanTable
|
||||
using VblHdr
|
||||
using VblRate
|
||||
|
||||
ldx #0 ; Load 0 into x register
|
||||
lda #0 ; Load 0 into accumulator
|
||||
clc ; Clear carry flag
|
||||
STL sta ScanTable,x ; Store accumulator in ScanTable+x
|
||||
adc #160 ; Add 160 to accumulator
|
||||
inx ; Increment x
|
||||
inx ; Increment x
|
||||
cpx #400 ; Compare x to 400 (200 scanlines)
|
||||
bcc STL ; Repeat Scan Table Loop until we do all 200 lines
|
||||
|
||||
lda h ; Store refresh rate / 10 in VblCount and VblRate
|
||||
sta >VblCount
|
||||
sta >VblRate
|
||||
|
||||
lda #42 ; Reset timer
|
||||
sta >VblTime
|
||||
|
||||
;ph4 #VblHdr ; Start VBL interrupt task
|
||||
;ldx #$1203 ;_SetHeartBeat
|
||||
;jsl $E10000
|
||||
|
||||
jreturn
|
||||
end
|
||||
|
||||
;----------------------------------------
|
||||
; Shut down assembly routines
|
||||
;----------------------------------------
|
||||
asmStop start
|
||||
jsubroutine
|
||||
|
||||
;ph4 #VblHdr ; Stop VBL interrupt task
|
||||
;ldx #$1303 ;_DelHeartBeat
|
||||
;jsl $E10000
|
||||
|
||||
jreturn
|
||||
end
|
||||
|
||||
;----------------------------------------
|
||||
; Increment time counter using VBLs every 1/10 second
|
||||
;----------------------------------------
|
||||
VblHdr data
|
||||
dc i4'0' ; Space for task pointer
|
||||
VblCount dc i2'1' ; How many VBLs between calls (1 only on initial call)
|
||||
dc i2'$A55A' ; Task signature
|
||||
end
|
||||
|
||||
VblTask start
|
||||
using VblHdr
|
||||
using VblRate
|
||||
using vblDBR
|
||||
long m ; 16 bit Accumulator
|
||||
phb ; Push Data Bank Register
|
||||
phb ; Push Data Bank Register
|
||||
pla ; Pull Accumulator
|
||||
sta >vblDBR ; Store Accumulator in savedDBR (Data Bank Register)
|
||||
phk ; Push K (Program Bank Register)
|
||||
plb ; Pull Data Bank Register
|
||||
lda >VblRate ; Reset counter
|
||||
sta >VblCount
|
||||
lda >VblTime ; Increment timer
|
||||
inc a
|
||||
sta >VblTime
|
||||
lda >vblDBR ; Load our saved Data Bank Register
|
||||
pha ; Push the C Accumulator
|
||||
plb ; Pull Data Bank Register
|
||||
plb ; Pull Data Bank Register
|
||||
short m ; Back to 8 bit Accumulator
|
||||
rtl
|
||||
end
|
332
src/jIIgs.c
Normal file
332
src/jIIgs.c
Normal file
|
@ -0,0 +1,332 @@
|
|||
/*
|
||||
* JoeyLib
|
||||
* Copyright (C) 2018 Scott Duensing <scott@kangaroopunch.com>
|
||||
*
|
||||
* This software is provided 'as-is', without any express 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <locator.h>
|
||||
#include <memory.h>
|
||||
#include <misctool.h>
|
||||
#include <sound.h>
|
||||
#undef false
|
||||
#undef true
|
||||
|
||||
|
||||
#define JOEY_LIBRARY
|
||||
#include "joey.h"
|
||||
|
||||
|
||||
#ifdef JOEY_DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
char length;
|
||||
char text[255];
|
||||
} _jlPascalStringT;
|
||||
|
||||
|
||||
extern void asmBorder(int c);
|
||||
extern void asmGrOff(void);
|
||||
extern void asmGrOn(void);
|
||||
extern int asmJoy(int which);
|
||||
extern void asmShOff(void);
|
||||
extern void asmShOn(void);
|
||||
extern void asmSlam(void);
|
||||
extern void asmStart(int myID, int hertzBy10);
|
||||
extern void asmStop(void);
|
||||
|
||||
|
||||
extern pascal void NTStartUp(Word) inline(0x02DD, dispatcher);
|
||||
extern pascal void NTShutDown(void) inline(0x03DD, dispatcher);
|
||||
extern pascal void NTLoadOneMusic(Pointer) inline(0x09DD, dispatcher);
|
||||
extern pascal void NTPlayMusic(Word) inline(0x0ADD, dispatcher);
|
||||
extern pascal Word NTGetPlayingMusic(void) inline(0x10DD, dispatcher);
|
||||
extern pascal void NTPauseMusic(void) inline(0x13DD, dispatcher);
|
||||
extern pascal void NTContinueMusic(void) inline(0x14DD, dispatcher);
|
||||
|
||||
|
||||
char _jlKeyCheck(char key);
|
||||
|
||||
|
||||
static byte *KEYBOARD = (byte *)0x00C000;
|
||||
static byte *KEYSTROBE = (byte *)0x00C010;
|
||||
static byte *BUTTON0 = (byte *)0x00C061;
|
||||
static byte *BUTTON1 = (byte *)0x00C062;
|
||||
static jlPixelPairT *SHRPIXELS = (jlPixelPairT *)0x012000; // Shadow of 0xE12000
|
||||
static byte *SHRSCB = (byte *)0x019D00; // Shadow of 0xE19D00
|
||||
static jlColorT *SHRCOLORS = (jlColorT *)0x019E00; // Shadow of 0xE19E00
|
||||
static byte *BORDER = (byte *)0xE0C034;
|
||||
|
||||
|
||||
static byte _jlBorderSaved;
|
||||
static int _jlMyID;
|
||||
static int _jlMemID;
|
||||
static int _jlMusicMemID;
|
||||
static Handle _jlSHRShadowHandle;
|
||||
static int _jlHertz;
|
||||
|
||||
|
||||
#ifdef JOEY_DEBUG
|
||||
#define JOEY_CHECK_TOOL_ERROR(w) if (_toolErr) _jlDieWithToolError(w, _toolErr);
|
||||
void _jlDieWithToolError(const char *what, int err) {
|
||||
char message[256];
|
||||
sprintf(message, "Tool Error %04X %s", err, what);
|
||||
jlUtilDie(message);
|
||||
}
|
||||
|
||||
void _jlDebugBorder(jlBorderColorsE color) {
|
||||
jlDisplayBorder(color);
|
||||
asmBorder(_jlBorderColor);
|
||||
//*BORDER = *BORDER & 0xF0 | _jlBorderColor;
|
||||
}
|
||||
#else
|
||||
#define JOEY_CHECK_TOOL_ERROR(w)
|
||||
#endif
|
||||
|
||||
|
||||
void jlDisplayPresent(void) {
|
||||
asmShOn();
|
||||
asmSlam();
|
||||
asmShOff();
|
||||
asmBorder(_jlBorderColor);
|
||||
}
|
||||
|
||||
|
||||
void jlDrawClear(void) {
|
||||
memset(SHRPIXELS, _jlDrawColorNibbles, 32000);
|
||||
}
|
||||
|
||||
|
||||
int jlGameGetAxis(byte which) {
|
||||
return asmJoy((int)which) - 128;
|
||||
}
|
||||
|
||||
|
||||
bool jlGameGetButton(byte which) {
|
||||
if (which > 0) return (bool)(*BUTTON1 > 127);
|
||||
return (bool)(*BUTTON0 > 127);
|
||||
}
|
||||
|
||||
|
||||
char _jlKeyCheck(char key) {
|
||||
if ((key < 8) || (key > 127)) {
|
||||
key = 0;
|
||||
} else {
|
||||
// Map LF to CR
|
||||
if (key == 10) {
|
||||
key = 13;
|
||||
}
|
||||
// Map DEL to BS
|
||||
if (key == 127) {
|
||||
key = 8;
|
||||
}
|
||||
// Is this outside the range we care about?
|
||||
if ((key < ' ') || (key > '~')) {
|
||||
if ((key != 8) && (key != 13) && (key != 27)) {
|
||||
key = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
bool jlKeyPressed(void) {
|
||||
bool result = false;
|
||||
// On other platforms we should call jlIdle() here.
|
||||
if ((*KEYBOARD & 0x80) != 0) {
|
||||
result = (_jlKeyCheck(*KEYBOARD & 0x7F) != 0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
char jlKeyRead(void) {
|
||||
// On other platforms we should call jlIdle() here.
|
||||
|
||||
// Reset keyboard strobe
|
||||
*KEYSTROBE = 0;
|
||||
|
||||
return _jlKeyCheck(*KEYBOARD & 0x7F);
|
||||
}
|
||||
|
||||
|
||||
void jlPaletteSet(byte index, byte r, byte g, byte b) {
|
||||
SHRCOLORS[index].r = r;
|
||||
SHRCOLORS[index].g = g;
|
||||
SHRCOLORS[index].b = b;
|
||||
}
|
||||
|
||||
|
||||
void jlSoundFree(jlSoundT *sound) {
|
||||
//***TODO***
|
||||
}
|
||||
|
||||
|
||||
bool jlSoundIsPlaying(jlSoundT *sound) {
|
||||
//***TODO***
|
||||
}
|
||||
|
||||
|
||||
bool _jlSoundLoad(jlSoundT **sound, char *filename) {
|
||||
//***TODO***
|
||||
}
|
||||
|
||||
|
||||
void jlSoundMusicContinue(void) {
|
||||
NTContinueMusic();
|
||||
}
|
||||
|
||||
|
||||
bool jlSoundMusicIsPlaying(void) {
|
||||
return (NTGetPlayingMusic() != 0xFFFF);
|
||||
}
|
||||
|
||||
|
||||
void jlSoundMusicPause(void) {
|
||||
NTPauseMusic();
|
||||
}
|
||||
|
||||
|
||||
void jlSoundMusicPlay(char *name) {
|
||||
_jlPascalStringT file;
|
||||
strcpy(file.text, name);
|
||||
file.length = strlen(name);
|
||||
NTStartUp(_jlMusicMemID);
|
||||
JOEY_CHECK_TOOL_ERROR("NTStartup")
|
||||
NTLoadOneMusic((Pointer)&file);
|
||||
JOEY_CHECK_TOOL_ERROR("NTLoadOneMusic")
|
||||
NTPlayMusic(false);
|
||||
JOEY_CHECK_TOOL_ERROR("NTPlayMusic")
|
||||
}
|
||||
|
||||
|
||||
void jlSoundMusicStop(void) {
|
||||
NTShutDown();
|
||||
JOEY_CHECK_TOOL_ERROR("NTShutDown")
|
||||
}
|
||||
|
||||
|
||||
void jlSoundPlay(jlSoundT *sound) {
|
||||
//***TODO***
|
||||
}
|
||||
|
||||
|
||||
bool _jlStaCreate(jlStaT **sta) {
|
||||
jlStaT *t = (jlStaT *)jlMalloc(sizeof(jlStaT));
|
||||
if (t != NULL) {
|
||||
memset(t, 0, sizeof(jlStaT));
|
||||
t->id[0] = 'S';
|
||||
t->id[1] = 'T';
|
||||
t->id[2] = 'A';
|
||||
t->version = 0;
|
||||
memcpy(t->palette, SHRCOLORS, sizeof(t->palette));
|
||||
memcpy(t->pixels, SHRPIXELS, sizeof(t->pixels));
|
||||
*sta = t;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void jlStaDisplay(jlStaT *sta) {
|
||||
memcpy(SHRCOLORS, sta->palette, sizeof(sta->palette));
|
||||
memcpy(SHRPIXELS, sta->pixels, sizeof(sta->pixels));
|
||||
}
|
||||
|
||||
|
||||
void jlUtilIdle(void) {
|
||||
// No need to pump the message loop on the IIgs
|
||||
}
|
||||
|
||||
|
||||
bool jlUtilMustExit(void) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void jlUtilShutdown(void) {
|
||||
// Clear the display.
|
||||
jlDrawColor(0);
|
||||
jlDrawClear();
|
||||
|
||||
// Restore Border
|
||||
jlDisplayBorder((jlBorderColorsE)_jlBorderSaved);
|
||||
jlDisplayPresent();
|
||||
|
||||
// SHR Off
|
||||
asmGrOff();
|
||||
|
||||
asmStop();
|
||||
|
||||
// Shutdown tools
|
||||
UnloadOneTool(0xDD); // NinjaTracker
|
||||
MTShutDown();
|
||||
DisposeAll(_jlMemID);
|
||||
MMShutDown(_jlMyID);
|
||||
TLShutDown();
|
||||
|
||||
jlUtilDie("Clean Exit.");
|
||||
}
|
||||
|
||||
|
||||
void jlUtilStartup(char *appName) {
|
||||
|
||||
(void)appName;
|
||||
|
||||
// Start up neded tools
|
||||
TLStartUp();
|
||||
_jlMyID = MMStartUp();
|
||||
_jlMemID = _jlMyID | 0x0100; // Set aux ID to 1.
|
||||
_jlMusicMemID = _jlMyID | 0x0200; // Set music ID.
|
||||
MTStartUp();
|
||||
LoadOneTool(0xDD, 0); // NinjaTracker
|
||||
JOEY_CHECK_TOOL_ERROR("LoadOneTool")
|
||||
|
||||
// Reserve shadow area for SHR
|
||||
_jlSHRShadowHandle = NewHandle((LongWord)0x8000, (Word)_jlMemID, (Word)(attrLocked + attrFixed + attrBank + attrAddr), (Pointer)0x012000);
|
||||
|
||||
// Start assembly module
|
||||
_jlHertz = (int)ReadBParam((Word)0x1D) == 0 ? 60 : 50; // Is this a PAL or NTSC machine?
|
||||
asmStart(_jlMyID, _jlHertz / 10);
|
||||
|
||||
// SHR on
|
||||
asmGrOn();
|
||||
|
||||
// If you work out the Screen Conrol Bytes, everything we want is zero.
|
||||
// So we just memset all 200 of them.
|
||||
memset(SHRSCB, 0, 200);
|
||||
|
||||
// Hide border.
|
||||
_jlBorderSaved = *BORDER & 0x0F;
|
||||
jlDisplayBorder(BORDER_BLACK);
|
||||
|
||||
jlPaletteDefault();
|
||||
|
||||
// Clear the display.
|
||||
jlDrawColor(0);
|
||||
jlDrawClear();
|
||||
jlDrawColor(15);
|
||||
|
||||
jlDisplayPresent();
|
||||
}
|
119
src/jIIgs.macro
Normal file
119
src/jIIgs.macro
Normal file
|
@ -0,0 +1,119 @@
|
|||
;
|
||||
; Based on M16.cc from ORCA/C
|
||||
;
|
||||
|
||||
MACRO
|
||||
&lab jsubroutine &parms,&work
|
||||
&lab anop
|
||||
using savedDBR ; ADDED
|
||||
aif c:&work,.a
|
||||
lclc &work
|
||||
&work setc 0
|
||||
.a
|
||||
gbla &totallen
|
||||
gbla &worklen
|
||||
&worklen seta &work
|
||||
&totallen seta 0
|
||||
aif c:&parms=0,.e
|
||||
lclc &len
|
||||
lclc &p
|
||||
lcla &i
|
||||
&i seta 1
|
||||
.b
|
||||
&p setc &parms(&i)
|
||||
&len amid &p,2,1
|
||||
aif "&len"=":",.c
|
||||
&len amid &p,1,2
|
||||
&p amid &p,4,l:&p-3
|
||||
ago .d
|
||||
.c
|
||||
&len amid &p,1,1
|
||||
&p amid &p,3,l:&p-2
|
||||
.d
|
||||
&p equ &totallen+4+&work
|
||||
&totallen seta &totallen+&len
|
||||
&i seta &i+1
|
||||
aif &i<=c:&parms,^b
|
||||
.e
|
||||
tsc
|
||||
aif &work=0,.f
|
||||
sec
|
||||
sbc #&work
|
||||
tcs
|
||||
.f
|
||||
phd ; Push Direct Register
|
||||
tcd ; Transfer C Accumulator to Direct Register
|
||||
|
||||
; === START OF OUR MODIFICATION ===
|
||||
phb ; Push Data Bank Register
|
||||
phb ; Push Data Bank Register
|
||||
pla ; Pull Accumulator
|
||||
sta >savedDBR ; Store Accumulator in savedDBR (Data Bank Register)
|
||||
phk ; Push K (Program Bank Register)
|
||||
plb ; Pull Data Bank Register
|
||||
; === END OF OUR MODIFICATION ===
|
||||
|
||||
mend
|
||||
|
||||
|
||||
MACRO
|
||||
&lab jreturn &r
|
||||
&lab anop
|
||||
|
||||
; === START OF OUR MODIFICATION ===
|
||||
using savedDBR
|
||||
lda >savedDBR ; Load our saved Data Bank Register
|
||||
pha ; Push the C Accumulator
|
||||
plb ; Pull Data Bank Register
|
||||
plb ; Pull Data Bank Register
|
||||
; === END OF OUR MODIFICATION ===
|
||||
|
||||
lclc &len
|
||||
aif c:&r,.a
|
||||
lclc &r
|
||||
&r setc 0
|
||||
&len setc 0
|
||||
ago .h
|
||||
.a
|
||||
&len amid &r,2,1
|
||||
aif "&len"=":",.b
|
||||
&len amid &r,1,2
|
||||
&r amid &r,4,l:&r-3
|
||||
ago .c
|
||||
.b
|
||||
&len amid &r,1,1
|
||||
&r amid &r,3,l:&r-2
|
||||
.c
|
||||
aif &len<>2,.d
|
||||
ldy &r
|
||||
ago .h
|
||||
.d
|
||||
aif &len<>4,.e
|
||||
ldx &r+2
|
||||
ldy &r
|
||||
ago .h
|
||||
.e
|
||||
aif &len<>10,.g
|
||||
ldy #&r
|
||||
ldx #^&r
|
||||
ago .h
|
||||
.g
|
||||
mnote 'Not a valid return length',16
|
||||
mexit
|
||||
.h
|
||||
aif &totallen=0,.i
|
||||
lda &worklen+2
|
||||
sta &worklen+&totallen+2
|
||||
lda &worklen+1
|
||||
sta &worklen+&totallen+1
|
||||
.i
|
||||
pld
|
||||
tsc
|
||||
clc
|
||||
adc #&worklen+&totallen
|
||||
tcs
|
||||
aif &len=0,.j
|
||||
tya
|
||||
.j
|
||||
rtl
|
||||
mend
|
546
src/jPC.c
Normal file
546
src/jPC.c
Normal file
|
@ -0,0 +1,546 @@
|
|||
/*
|
||||
* JoeyLib
|
||||
* Copyright (C) 2018 Scott Duensing <scott@kangaroopunch.com>
|
||||
*
|
||||
* This software is provided 'as-is', without any express 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "SDL2/SDL.h"
|
||||
#include "SDL2/SDL_mixer.h"
|
||||
|
||||
#define JOEY_LIBRARY
|
||||
#include "joey.h"
|
||||
|
||||
|
||||
static SDL_Window *_jlWindow = NULL;
|
||||
static SDL_Renderer *_jlRenderer = NULL;
|
||||
static jlStaT *_jlBackingStore = NULL; // 4 bit representation
|
||||
static SDL_Texture *_jlTexture = NULL; // Video card representation in ARGB
|
||||
static SDL_PixelFormat *_jlPixelFormat = NULL; // Pixel format of _jlTexture
|
||||
static bool _jlIsRunning = true;
|
||||
static int _jlNumKeysDown = 0;
|
||||
static char _jlLastKey = 0;
|
||||
static Mix_Music *_jlMusicHandle = NULL;
|
||||
static SDL_GameController **_jlControllers = NULL;
|
||||
static int _jlControllerCount = 0;
|
||||
static unsigned int _jlTimerValue = 0;
|
||||
static SDL_TimerID _jlTimerId = 0;
|
||||
|
||||
|
||||
Uint32 _jlUtilTimer(Uint32 interval, void *param);
|
||||
|
||||
|
||||
/*
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
|
||||
Uint32 _jlGetPixel(SDL_Surface *surface, int x, int y) {
|
||||
|
||||
int bpp = surface->format->BytesPerPixel;
|
||||
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
|
||||
|
||||
switch(bpp) {
|
||||
case 1:
|
||||
return *p;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Generates cast increases required alignment of target type [-Wcast-align] warning. Harmless on x86.
|
||||
return *(Uint16 *)p;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
|
||||
return (Uint32)(p[0] << 16 | p[1] << 8 | p[2]);
|
||||
else
|
||||
return (Uint32)(p[0] | p[1] << 8 | p[2] << 16);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
// Generates cast increases required alignment of target type [-Wcast-align] warning. Harmless on x86.
|
||||
return *(Uint32 *)p;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void _jlPutPixel(SDL_Surface *surface, int x, int y, Uint32 pixel) {
|
||||
|
||||
int bpp = surface->format->BytesPerPixel;
|
||||
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
|
||||
|
||||
switch(bpp) {
|
||||
case 1:
|
||||
*p = (Uint8)pixel;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
*(Uint16 *)p = (Uint16)pixel;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
|
||||
p[0] = (pixel >> 16) & 0xff;
|
||||
p[1] = (pixel >> 8) & 0xff;
|
||||
p[2] = pixel & 0xff;
|
||||
} else {
|
||||
p[0] = pixel & 0xff;
|
||||
p[1] = (pixel >> 8) & 0xff;
|
||||
p[2] = (pixel >> 16) & 0xff;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
*(Uint32 *)p = pixel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
*/
|
||||
|
||||
|
||||
void jlDisplayPresent(void) {
|
||||
// Render 4 bit copy to proper pixel format.
|
||||
// This extra step preserves palette effects.
|
||||
//***TODO*** Fake border colors on PC
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int pitch = 0;
|
||||
void *pixelData = NULL;
|
||||
jlUtilIdle();
|
||||
SDL_LockTexture(_jlTexture, NULL, &pixelData, &pitch);
|
||||
Uint32 *pixels = (Uint32 *)pixelData;
|
||||
for (int y=0; y<200; y++) {
|
||||
for (int x=0; x<160; x++) {
|
||||
// We decode this R/L instead of L/R for some reason. NO idea why yet. Endians?
|
||||
pixels[i++] = SDL_MapRGBA(_jlPixelFormat,
|
||||
_jlBackingStore->palette[_jlBackingStore->pixels[j].r].r * 16,
|
||||
_jlBackingStore->palette[_jlBackingStore->pixels[j].r].g * 16,
|
||||
_jlBackingStore->palette[_jlBackingStore->pixels[j].r].b * 16,
|
||||
255);
|
||||
pixels[i++] = SDL_MapRGBA(_jlPixelFormat,
|
||||
_jlBackingStore->palette[_jlBackingStore->pixels[j].l].r * 16,
|
||||
_jlBackingStore->palette[_jlBackingStore->pixels[j].l].g * 16,
|
||||
_jlBackingStore->palette[_jlBackingStore->pixels[j].l].b * 16,
|
||||
255);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
SDL_UnlockTexture(_jlTexture);
|
||||
|
||||
SDL_RenderCopy(_jlRenderer, _jlTexture, NULL, NULL);
|
||||
SDL_RenderPresent(_jlRenderer);
|
||||
}
|
||||
|
||||
|
||||
void jlDrawBlit8x8(jlStaT *sta, int cx1, int cy1, int cx2, int cy2) {
|
||||
int o1;
|
||||
int o2;
|
||||
int x;
|
||||
int y;
|
||||
|
||||
o1 = (cy1 * 8 * 160) + (cx1 * 4);
|
||||
o2 = (cy2 * 8 * 160) + (cx2 * 4);
|
||||
|
||||
for (y=0; y<8; y++) {
|
||||
for (x=0; x<4; x++) {
|
||||
_jlBackingStore->pixels[o2++] = sta->pixels[o1++];
|
||||
}
|
||||
o1 += 156;
|
||||
o2 += 156;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void jlDrawClear(void) {
|
||||
memset(_jlBackingStore->pixels, _jlDrawColorNibbles, 32000);
|
||||
}
|
||||
|
||||
|
||||
byte jlDrawGetPixel(int x, int y) {
|
||||
int p = x / 2 + y * 160;
|
||||
return (jlUtilIsOdd(x) ? _jlBackingStore->pixels[p].l : _jlBackingStore->pixels[p].r);
|
||||
}
|
||||
|
||||
|
||||
void jlDrawPoint(int x, int y) {
|
||||
jlPixelPairT *pixelPair = _jlBackingStore->pixels + (y * 160) + (x / 2);
|
||||
if (jlUtilIsOdd(x)) {
|
||||
pixelPair->l = _jlDrawColor;
|
||||
} else {
|
||||
pixelPair->r = _jlDrawColor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int jlGameGetAxis(byte which) {
|
||||
SDL_GameControllerAxis axis;
|
||||
short int unscaled;
|
||||
short int max = SHRT_MIN;
|
||||
short int min = SHRT_MAX;
|
||||
int x;
|
||||
|
||||
jlUtilIdle();
|
||||
|
||||
if (which == 0) {
|
||||
axis = SDL_CONTROLLER_AXIS_LEFTX;
|
||||
} else {
|
||||
axis = SDL_CONTROLLER_AXIS_LEFTY;
|
||||
}
|
||||
|
||||
for (x=0; x<_jlControllerCount; x++) {
|
||||
unscaled = SDL_GameControllerGetAxis(_jlControllers[x], axis);
|
||||
if (unscaled > 0) {
|
||||
if (unscaled > max) {
|
||||
max = unscaled;
|
||||
}
|
||||
} else {
|
||||
if (unscaled < min) {
|
||||
min = unscaled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (-min > max ? min : max) / 256;
|
||||
}
|
||||
|
||||
|
||||
bool jlGameGetButton(byte which) {
|
||||
SDL_GameControllerButton button;
|
||||
int x;
|
||||
bool pressed = false;
|
||||
|
||||
jlUtilIdle();
|
||||
|
||||
if (which == 0) {
|
||||
button = SDL_CONTROLLER_BUTTON_A;
|
||||
} else {
|
||||
button = SDL_CONTROLLER_BUTTON_B;
|
||||
}
|
||||
|
||||
for (x=0; x<_jlControllerCount; x++) {
|
||||
if (SDL_GameControllerGetButton(_jlControllers[x], button)) {
|
||||
pressed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pressed;
|
||||
}
|
||||
|
||||
|
||||
bool jlKeyPressed(void) {
|
||||
jlUtilIdle();
|
||||
return (_jlNumKeysDown > 0);
|
||||
}
|
||||
|
||||
|
||||
char jlKeyRead(void) {
|
||||
jlUtilIdle();
|
||||
return _jlLastKey;
|
||||
}
|
||||
|
||||
|
||||
void jlPaletteSet(byte index, byte r, byte g, byte b) {
|
||||
_jlBackingStore->palette[index].r = r;
|
||||
_jlBackingStore->palette[index].g = g;
|
||||
_jlBackingStore->palette[index].b = b;
|
||||
}
|
||||
|
||||
|
||||
void jlSoundFree(jlSoundT *sound) {
|
||||
if (sound != NULL) {
|
||||
if (sound->data != NULL) {
|
||||
Mix_FreeChunk((Mix_Chunk *)sound->data);
|
||||
}
|
||||
jlFree(sound);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool jlSoundIsPlaying(jlSoundT *sound) {
|
||||
return (Mix_Playing(sound->channel) > 0);
|
||||
}
|
||||
|
||||
|
||||
bool _jlSoundLoad(jlSoundT **sound, char *filename) {
|
||||
bool result = false;
|
||||
Mix_Chunk *sample;
|
||||
sample = Mix_LoadWAV(filename);
|
||||
if (sample) {
|
||||
if (*sound != NULL) {
|
||||
jlSoundFree(*sound);
|
||||
}
|
||||
jlSoundT *t = (jlSoundT *)jlMalloc(sizeof(jlSoundT));
|
||||
if (t != NULL) {
|
||||
t->data = (void *)sample;
|
||||
*sound = t;
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void jlSoundMusicContinue(void) {
|
||||
Mix_ResumeMusic();
|
||||
}
|
||||
|
||||
|
||||
bool jlSoundMusicIsPlaying(void) {
|
||||
return (bool)Mix_PlayingMusic();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void jlSoundMusicPause(void) {
|
||||
Mix_PauseMusic();
|
||||
}
|
||||
|
||||
|
||||
void jlSoundMusicPlay(char *name) {
|
||||
char temp[256];
|
||||
if (_jlMusicHandle != NULL) {
|
||||
jlSoundMusicStop();
|
||||
}
|
||||
snprintf(temp, 256, "%s.mod", name);
|
||||
_jlMusicHandle = Mix_LoadMUS(temp);
|
||||
if (_jlMusicHandle != NULL) {
|
||||
Mix_PlayMusic(_jlMusicHandle, 1);
|
||||
} else {
|
||||
printf("Unable to load %s\n", temp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void jlSoundMusicStop(void) {
|
||||
if (jlSoundMusicIsPlaying()) {
|
||||
Mix_HaltMusic();
|
||||
}
|
||||
if (_jlMusicHandle != NULL) {
|
||||
Mix_FreeMusic(_jlMusicHandle);
|
||||
_jlMusicHandle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void jlSoundPlay(jlSoundT *sound) {
|
||||
sound->channel = Mix_PlayChannel(-1, (Mix_Chunk *)sound->data, 0);
|
||||
}
|
||||
|
||||
|
||||
bool _jlStaCreate(jlStaT **sta) {
|
||||
jlStaT *t = (jlStaT *)jlMalloc(sizeof(jlStaT));
|
||||
if (t != NULL) {
|
||||
memset(t, 0, sizeof(jlStaT));
|
||||
t->id[0] = 'S';
|
||||
t->id[1] = 'T';
|
||||
t->id[2] = 'A';
|
||||
t->version = 0;
|
||||
// Backing store does not exist at startup
|
||||
if (_jlBackingStore != NULL) {
|
||||
memcpy(t->palette, _jlBackingStore->palette, sizeof(t->palette));
|
||||
memcpy(t->pixels, _jlBackingStore->pixels, sizeof(t->pixels));
|
||||
}
|
||||
*sta = t;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void jlStaDisplay(jlStaT *sta) {
|
||||
memcpy(_jlBackingStore->palette, sta->palette, sizeof(sta->palette));
|
||||
memcpy(_jlBackingStore->pixels, sta->pixels, sizeof(sta->pixels));
|
||||
}
|
||||
|
||||
|
||||
char _jlUtilIdleCheckKey(int sym) {
|
||||
|
||||
char key = 0;
|
||||
|
||||
// Do we even care about this key?
|
||||
if ((sym < 8) || (sym > 127)) {
|
||||
key = 0;
|
||||
} else {
|
||||
SDL_Keymod mod = SDL_GetModState();
|
||||
key = (char)sym;
|
||||
// Map LF to CR
|
||||
if (key == 10) {
|
||||
key = 13;
|
||||
}
|
||||
// Map DEL to BS
|
||||
if (key == 127) {
|
||||
key = 8;
|
||||
}
|
||||
// Convert to uppercase if needed
|
||||
if ((mod == KMOD_SHIFT) && (key >= 'a') && (key <= 'z')) {
|
||||
key -= 32;
|
||||
}
|
||||
// Is this outside the range we care about?
|
||||
if ((key < ' ') || (key > '~')) {
|
||||
if ((key != 8) && (key != 13) && (key != 27)) {
|
||||
key = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
void jlUtilIdle(void) {
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
switch(event.type) {
|
||||
case SDL_KEYDOWN:
|
||||
// Track keydown/keyup and remember last key pressed.
|
||||
switch (event.key.keysym.sym) {
|
||||
case SDLK_F1:
|
||||
//SDL_RenderSetScale(_jlRenderer, 1.0f, 1.0f);
|
||||
SDL_SetWindowSize(_jlWindow, 320, 200);
|
||||
break;
|
||||
|
||||
case SDLK_F2:
|
||||
//SDL_RenderSetScale(_jlRenderer, 2.0f, 2.0f);
|
||||
SDL_SetWindowSize(_jlWindow, 640, 400);
|
||||
break;
|
||||
|
||||
case SDLK_F3:
|
||||
//SDL_RenderSetScale(_jlRenderer, 3.0f, 3.0f);
|
||||
SDL_SetWindowSize(_jlWindow, 860, 600);
|
||||
break;
|
||||
|
||||
default:
|
||||
_jlLastKey = _jlUtilIdleCheckKey(event.key.keysym.sym);
|
||||
if (_jlLastKey > 0) {
|
||||
_jlNumKeysDown++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SDL_KEYUP:
|
||||
if (_jlUtilIdleCheckKey(event.key.keysym.sym) > 0) {
|
||||
_jlNumKeysDown--;
|
||||
}
|
||||
break;
|
||||
|
||||
case SDL_QUIT:
|
||||
_jlIsRunning = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_Delay(1);
|
||||
}
|
||||
|
||||
|
||||
bool jlUtilMustExit(void) {
|
||||
return !_jlIsRunning;
|
||||
}
|
||||
|
||||
|
||||
void jlUtilShutdown(void) {
|
||||
int x;
|
||||
|
||||
SDL_RemoveTimer(_jlTimerId);
|
||||
for (x=0; x<_jlControllerCount; x++) {
|
||||
SDL_GameControllerClose(_jlControllers[x]);
|
||||
}
|
||||
_jlControllerCount = 0;
|
||||
jlFree(_jlControllers);
|
||||
jlStaFree(_jlBackingStore);
|
||||
jlSoundMusicStop();
|
||||
Mix_CloseAudio();
|
||||
Mix_Quit();
|
||||
SDL_FreeFormat(_jlPixelFormat);
|
||||
SDL_DestroyTexture(_jlTexture);
|
||||
SDL_DestroyRenderer(_jlRenderer);
|
||||
SDL_DestroyWindow(_jlWindow);
|
||||
SDL_Quit();
|
||||
jlUtilDie("Clean Exit.");
|
||||
}
|
||||
|
||||
|
||||
void jlUtilStartup(char *appName) {
|
||||
|
||||
int flags;
|
||||
int result;
|
||||
int joysticks;
|
||||
int x;
|
||||
|
||||
// Start low-level tools
|
||||
if (SDL_Init(SDL_INIT_EVERYTHING) == -1) {
|
||||
jlUtilDie(SDL_GetError());
|
||||
}
|
||||
|
||||
// Start audio mixer & music system.
|
||||
flags = MIX_INIT_MOD;
|
||||
result = Mix_Init(flags);
|
||||
if ((result & flags) != flags) {
|
||||
jlUtilDie(Mix_GetError());
|
||||
}
|
||||
if (Mix_OpenAudio(22050, MIX_DEFAULT_FORMAT, 2, 4096 ) == -1) {
|
||||
jlUtilDie(Mix_GetError());
|
||||
}
|
||||
|
||||
// Set up controllers
|
||||
joysticks = SDL_NumJoysticks();
|
||||
_jlControllers = (SDL_GameController **)jlMalloc(sizeof(SDL_GameController *) * (unsigned long)joysticks);
|
||||
for (x=0; x<joysticks; x++) {
|
||||
if (SDL_IsGameController(x)) {
|
||||
_jlControllers[_jlControllerCount++] = SDL_GameControllerOpen(x);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a window and renderer using SDL
|
||||
_jlWindow = SDL_CreateWindow(appName, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 400, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
|
||||
_jlRenderer = SDL_CreateRenderer(_jlWindow, -1, SDL_RENDERER_SOFTWARE);
|
||||
_jlTexture = SDL_CreateTexture(_jlRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 320, 200);
|
||||
_jlPixelFormat = SDL_AllocFormat(SDL_GetWindowPixelFormat(_jlWindow));
|
||||
|
||||
// Create backing store
|
||||
jlStaCreate(_jlBackingStore);
|
||||
jlPaletteDefault();
|
||||
jlDrawColor(0);
|
||||
jlDrawClear();
|
||||
jlDrawColor(15);
|
||||
jlDisplayPresent();
|
||||
|
||||
// Start 1/10th second timer
|
||||
_jlTimerId = SDL_AddTimer(100, _jlUtilTimer, NULL);
|
||||
}
|
||||
|
||||
|
||||
Uint32 _jlUtilTimer(Uint32 interval, void *param) {
|
||||
(void)param;
|
||||
_jlTimerValue++;
|
||||
return(interval);
|
||||
}
|
||||
|
||||
|
||||
unsigned int jlUtilTimer(void) {
|
||||
return _jlTimerValue;
|
||||
}
|
763
src/joey.c
Normal file
763
src/joey.c
Normal file
|
@ -0,0 +1,763 @@
|
|||
/*
|
||||
* JoeyLib
|
||||
* Copyright (C) 2018 Scott Duensing <scott@kangaroopunch.com>
|
||||
*
|
||||
* This software is provided 'as-is', without any express 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
#define JOEY_LIBRARY
|
||||
#include "joey.h"
|
||||
|
||||
|
||||
#include "stddclmr.h"
|
||||
|
||||
|
||||
// Vector image file command bytes
|
||||
#define COMMAND_COLOR 1 // C
|
||||
#define COMMAND_CLEAR 2 // E
|
||||
#define COMMAND_PLOT 3 // D (Draw)
|
||||
#define COMMAND_LINE 4 // L
|
||||
#define COMMAND_FILL 5 // F
|
||||
#define COMMAND_PALETTE 6 // P
|
||||
#define COMMAND_RESET 7 // R
|
||||
#define COMMAND_HBOX 8 // B (Box)
|
||||
#define COMMAND_FBOX 9 // S (Solid Box)
|
||||
#define COMMAND_FILLTO 10 // T (FillTo)
|
||||
|
||||
#define VEC_SCALE_DOWN 0.8 // 256/320
|
||||
#define VEC_SCALE_UP 1.25 // 320/256
|
||||
|
||||
|
||||
typedef struct {
|
||||
int StartX;
|
||||
int EndX;
|
||||
int Y;
|
||||
signed char Dir; // 'signed' needs to be specified for ORCA/C
|
||||
bool ScanLeft;
|
||||
bool ScanRight;
|
||||
bool padding; // Aligns structure on x86
|
||||
} _jlScanDataT;
|
||||
|
||||
|
||||
byte _jlDrawColor = 15; // Color in lower nibble only
|
||||
byte _jlDrawColorNibbles = (15 << 4) + 15; // Color in both nibbles
|
||||
byte _jlBorderColor = 0;
|
||||
|
||||
|
||||
static jlColorT _jlDefaultPalette[16];
|
||||
static jlStackT *_jlFillStackTop = NULL;
|
||||
static byte _jlDrawFillColor = 0;
|
||||
|
||||
|
||||
void _jlDrawCircleClipped(int x0, int y0, int radius);
|
||||
void _jlDrawFill(int x, int y, bool how);
|
||||
void _jlDrawFillAddLine(int startX, int endX, int y, int ignoreStart, int ignoreEnd, char dir, bool isNextInDir, bool how);
|
||||
_jlScanDataT *_jlDrawFillNewSegment(int startX, int endX, int y, signed char dir, bool scanLeft, bool scanRight);
|
||||
|
||||
|
||||
#ifdef JOEY_DEBUG
|
||||
|
||||
static jlMemoryBlockT _jlMemoryBlocks[JOEY_MEM_BLOCKS];
|
||||
static long _jlTotalAllocated = 0;
|
||||
static long _jlTotalAllocations = 0;
|
||||
static long _jlTotalFrees = 0;
|
||||
static long _jlHighWaterMark = 0;
|
||||
static long _jlBlocksNeeded = 0;
|
||||
static bool _jlMemoryStarted = false;
|
||||
|
||||
void _jlFree(void **pointer) {
|
||||
int i;
|
||||
|
||||
_jlTotalFrees++;
|
||||
if (*pointer != NULL) {
|
||||
for (i=0; i<JOEY_MEM_BLOCKS; i++) {
|
||||
if (_jlMemoryBlocks[i].addr == *pointer) {
|
||||
_jlTotalAllocated -= _jlMemoryBlocks[i].size;
|
||||
_jlMemoryBlocks[i].addr = 0;
|
||||
_jlMemoryBlocks[i].size = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= JOEY_MEM_BLOCKS) jlUtilDie("Block not found in jlFree()!");
|
||||
|
||||
free(*pointer);
|
||||
*pointer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void *_jlMalloc(size_t size, int line, char *file) {
|
||||
int i;
|
||||
|
||||
if (!_jlMemoryStarted) {
|
||||
memset(_jlMemoryBlocks, 0, sizeof(_jlMemoryBlocks));
|
||||
_jlMemoryStarted = true;
|
||||
}
|
||||
|
||||
_jlTotalAllocations++;
|
||||
for (i=0; i<JOEY_MEM_BLOCKS; i++) {
|
||||
if (_jlMemoryBlocks[i].addr == 0) {
|
||||
_jlMemoryBlocks[i].addr = malloc(size);
|
||||
_jlMemoryBlocks[i].size = size;
|
||||
_jlMemoryBlocks[i].line = line;
|
||||
_jlMemoryBlocks[i].file = file;
|
||||
if (i + 1 > _jlBlocksNeeded) _jlBlocksNeeded = i + 1;
|
||||
if (_jlMemoryBlocks[i].addr == NULL) jlUtilDie("Unable to allocate memory in jlMalloc()!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= JOEY_MEM_BLOCKS) jlUtilDie("No free blocks for jlMalloc()!");
|
||||
|
||||
_jlTotalAllocated += size;
|
||||
if (_jlTotalAllocated > _jlHighWaterMark) {
|
||||
_jlHighWaterMark = _jlTotalAllocated;
|
||||
}
|
||||
|
||||
return _jlMemoryBlocks[i].addr;
|
||||
}
|
||||
|
||||
void *_jlRealloc(void *pointer, size_t size) {
|
||||
int i = 0;
|
||||
size_t diff = 0;
|
||||
|
||||
if (pointer != NULL) {
|
||||
for (i=0; i<JOEY_MEM_BLOCKS; i++) {
|
||||
if (_jlMemoryBlocks[i].addr == pointer) {
|
||||
diff = size - _jlMemoryBlocks[i].size;
|
||||
_jlMemoryBlocks[i].size = size;
|
||||
_jlMemoryBlocks[i].addr = realloc(_jlMemoryBlocks[i].addr, size);
|
||||
if (_jlMemoryBlocks[i].addr == NULL) jlUtilDie("Unable to allocate memory in jlRealloc()!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i >= JOEY_MEM_BLOCKS) jlUtilDie("No matching block for jlRealloc()!");
|
||||
|
||||
_jlTotalAllocated += diff;
|
||||
if (_jlTotalAllocated > _jlHighWaterMark) {
|
||||
_jlHighWaterMark = _jlTotalAllocated;
|
||||
}
|
||||
|
||||
return _jlMemoryBlocks[i].addr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
void jlDisplayBorder(jlBorderColorsE color) {
|
||||
_jlBorderColor = (byte)color;
|
||||
}
|
||||
|
||||
|
||||
void jlDrawBox(int x1, int y1, int x2, int y2) {
|
||||
jlDrawLine(x1, y1, x2, y1);
|
||||
jlDrawLine(x2, y1, x2, y2);
|
||||
jlDrawLine(x2, y2, x1, y2);
|
||||
jlDrawLine(x1, y2, x1, y1);
|
||||
}
|
||||
|
||||
|
||||
void jlDrawBoxFilled(int x1, int y1, int x2, int y2) {
|
||||
int y;
|
||||
for (y=y1; y<=y2; y++) {
|
||||
jlDrawLine(x1, y, x2, y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void _jlDrawCircleClipped(int x0, int y0, int radius) {
|
||||
int x = radius-1;
|
||||
int y = 0;
|
||||
int dx = 1;
|
||||
int dy = 1;
|
||||
int err = dx - (radius << 1);
|
||||
|
||||
while (x >= y) {
|
||||
if ((x0 + x < 320) && (y0 + y < 200)) jlDrawPoint(x0 + x, y0 + y);
|
||||
if ((x0 + y < 320) && (y0 + x < 200)) jlDrawPoint(x0 + y, y0 + x);
|
||||
if ((x0 - y < 320) && (y0 + x < 200)) jlDrawPoint(x0 - y, y0 + x);
|
||||
if ((x0 - x < 320) && (y0 + y < 200)) jlDrawPoint(x0 - x, y0 + y);
|
||||
if ((x0 - x < 320) && (y0 - y < 200)) jlDrawPoint(x0 - x, y0 - y);
|
||||
if ((x0 - x < 320) && (y0 - x < 200)) jlDrawPoint(x0 - y, y0 - x);
|
||||
if ((x0 + y < 320) && (y0 - x < 200)) jlDrawPoint(x0 + y, y0 - x);
|
||||
if ((x0 + x < 320) && (y0 - y < 200)) jlDrawPoint(x0 + x, y0 - y);
|
||||
|
||||
if (err <= 0) {
|
||||
y++;
|
||||
err += dy;
|
||||
dy += 2;
|
||||
}
|
||||
|
||||
if (err > 0) {
|
||||
x--;
|
||||
dx += 2;
|
||||
err += dx - (radius << 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void jlDrawCircle(int x0, int y0, int radius) {
|
||||
int x = radius-1;
|
||||
int y = 0;
|
||||
int dx = 1;
|
||||
int dy = 1;
|
||||
int err = dx - (radius << 1);
|
||||
|
||||
// Is any of this going to be off the screen?
|
||||
//***TODO*** All our drawing primitives should do this.
|
||||
if ((x0 + radius > 319) || (x0 - radius < 0) || (y0 + radius > 199) || (y0 - radius < 0)) {
|
||||
_jlDrawCircleClipped(x0, y0, radius);
|
||||
return;
|
||||
}
|
||||
|
||||
while (x >= y) {
|
||||
jlDrawPoint(x0 + x, y0 + y);
|
||||
jlDrawPoint(x0 + y, y0 + x);
|
||||
jlDrawPoint(x0 - y, y0 + x);
|
||||
jlDrawPoint(x0 - x, y0 + y);
|
||||
jlDrawPoint(x0 - x, y0 - y);
|
||||
jlDrawPoint(x0 - y, y0 - x);
|
||||
jlDrawPoint(x0 + y, y0 - x);
|
||||
jlDrawPoint(x0 + x, y0 - y);
|
||||
|
||||
if (err <= 0) {
|
||||
y++;
|
||||
err += dy;
|
||||
dy += 2;
|
||||
}
|
||||
|
||||
if (err > 0) {
|
||||
x--;
|
||||
dx += 2;
|
||||
err += dx - (radius << 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void jlDrawColor(byte index) {
|
||||
_jlDrawColor = index;
|
||||
_jlDrawColorNibbles = (byte)((index << 4) + index);
|
||||
}
|
||||
|
||||
|
||||
// http://members.chello.at/~easyfilter/bresenham.html
|
||||
void jlDrawEllipse(int x0, int y0, int x1, int y1) {
|
||||
int a = abs(x1-x0), b = abs(y1-y0), b1 = b&1; /* values of diameter */
|
||||
long dx = 4*(1-a)*b*b, dy = 4*(b1+1)*a*a; /* error increment */
|
||||
long err = dx+dy+b1*a*a, e2; /* error of 1.step */
|
||||
|
||||
if (x0 > x1) { x0 = x1; x1 += a; } /* if called with swapped points */
|
||||
if (y0 > y1) y0 = y1; /* .. exchange them */
|
||||
y0 += (b+1)/2; y1 = y0-b1; /* starting pixel */
|
||||
a *= 8*a; b1 = 8*b*b;
|
||||
|
||||
do {
|
||||
jlDrawPoint(x1, y0); /* I. Quadrant */
|
||||
jlDrawPoint(x0, y0); /* II. Quadrant */
|
||||
jlDrawPoint(x0, y1); /* III. Quadrant */
|
||||
jlDrawPoint(x1, y1); /* IV. Quadrant */
|
||||
e2 = 2*err;
|
||||
if (e2 <= dy) { y0++; y1--; err += dy += a; } /* y step */
|
||||
if (e2 >= dx || 2*err > dy) { x0++; x1--; err += dx += b1; } /* x step */
|
||||
} while (x0 <= x1);
|
||||
|
||||
while (y0-y1 < b) { /* too early stop of flat ellipses a=1 */
|
||||
jlDrawPoint(x0-1, y0); /* -> finish tip of ellipse */
|
||||
jlDrawPoint(x1+1, y0++);
|
||||
jlDrawPoint(x0-1, y1);
|
||||
jlDrawPoint(x1+1, y1--);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_jlScanDataT *_jlDrawFillNewSegment(int startX, int endX, int y, signed char dir, bool scanLeft, bool scanRight) {
|
||||
_jlScanDataT *s = (_jlScanDataT *)jlMalloc(sizeof(_jlScanDataT));
|
||||
s->StartX = startX;
|
||||
s->EndX = endX;
|
||||
s->Y = y;
|
||||
s->Dir = dir;
|
||||
s->ScanLeft = scanLeft;
|
||||
s->ScanRight = scanRight;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
void _jlDrawFillAddLine(int startX, int endX, int y, int ignoreStart, int ignoreEnd, char dir, bool isNextInDir, bool how) {
|
||||
int regionStart = -1;
|
||||
int x;
|
||||
|
||||
for (x=startX; x<endX; x++) {
|
||||
if (how) {
|
||||
// Unrolled conents to reduce comparison complexity.
|
||||
if ((isNextInDir || x < ignoreStart || x >= ignoreEnd) && (jlDrawGetPixel(x, y) == _jlDrawFillColor)) {
|
||||
jlDrawPoint(x, y);
|
||||
if (regionStart < 0) regionStart = x;
|
||||
} else if (regionStart >= 0) {
|
||||
jlUtilStackPush(_jlFillStackTop, _jlDrawFillNewSegment(regionStart, x, y, dir, regionStart == startX, false));
|
||||
regionStart = -1;
|
||||
}
|
||||
} else {
|
||||
// Unrolled conents to reduce comparison complexity.
|
||||
if ((isNextInDir || x < ignoreStart || x >= ignoreEnd) && (jlDrawGetPixel(x, y) != _jlDrawFillColor)) {
|
||||
jlDrawPoint(x, y);
|
||||
if (regionStart < 0) regionStart = x;
|
||||
} else if (regionStart >= 0) {
|
||||
jlUtilStackPush(_jlFillStackTop, _jlDrawFillNewSegment(regionStart, x, y, dir, regionStart == startX, false));
|
||||
regionStart = -1;
|
||||
}
|
||||
}
|
||||
if (!isNextInDir && x < ignoreEnd && x >= ignoreStart) x = ignoreEnd-1;
|
||||
}
|
||||
if (regionStart >= 0) {
|
||||
jlUtilStackPush(_jlFillStackTop, _jlDrawFillNewSegment(regionStart, x, y, dir, regionStart == startX, true));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Stole this from http://www.adammil.net/blog/v126_A_More_Efficient_Flood_Fill.html
|
||||
void _jlDrawFill(int x, int y, bool how) {
|
||||
int height = 200;
|
||||
int width = 320;
|
||||
_jlScanDataT *r;
|
||||
int startX;
|
||||
int endX;
|
||||
|
||||
// how == true; Fill on top of _jlDrawFillColor
|
||||
// how == false; Fill on top of any color until we encounter _jlDrawFillColor
|
||||
|
||||
jlDrawPoint(x, y);
|
||||
|
||||
jlUtilStackPush(_jlFillStackTop, _jlDrawFillNewSegment(x, x+1, y, 0, true, true));
|
||||
while ((r = jlUtilStackPop(_jlFillStackTop)) != NULL) {
|
||||
startX = r->StartX;
|
||||
endX = r->EndX;
|
||||
if (r->ScanLeft) {
|
||||
if (how) {
|
||||
while (startX > 0 && (jlDrawGetPixel(startX-1, r->Y) == _jlDrawFillColor)) jlDrawPoint(--startX, r->Y);
|
||||
} else {
|
||||
while (startX > 0 && (jlDrawGetPixel(startX-1, r->Y) != _jlDrawFillColor)) jlDrawPoint(--startX, r->Y);
|
||||
}
|
||||
}
|
||||
if (r->ScanRight) {
|
||||
if (how) {
|
||||
while(endX < width && (jlDrawGetPixel(endX, r->Y) == _jlDrawFillColor)) jlDrawPoint(endX++, r->Y);
|
||||
} else {
|
||||
while(endX < width && (jlDrawGetPixel(endX, r->Y) == _jlDrawFillColor)) jlDrawPoint(endX++, r->Y);
|
||||
}
|
||||
}
|
||||
r->StartX--;
|
||||
r->EndX++;
|
||||
if (r->Y > 0) _jlDrawFillAddLine(startX, endX, r->Y-1, r->StartX, r->EndX, -1, r->Dir <= 0, how);
|
||||
if (r->Y < height-1) _jlDrawFillAddLine(startX, endX, r->Y+1, r->StartX, r->EndX, 1, r->Dir >= 0, how);
|
||||
jlFree(r);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void jlDrawFill(int x, int y) {
|
||||
_jlDrawFillColor = jlDrawGetPixel(x, y);
|
||||
_jlDrawFill(x, y, true);
|
||||
}
|
||||
|
||||
|
||||
void jlDrawFillTo(int x, int y, byte color) {
|
||||
_jlDrawFillColor = color;
|
||||
_jlDrawFill(x, y, false);
|
||||
}
|
||||
|
||||
|
||||
void jlDrawLine(int x1, int y1, int x2, int y2) {
|
||||
int x;
|
||||
int y;
|
||||
int dx;
|
||||
int dy;
|
||||
int incX;
|
||||
int incY;
|
||||
int balance;
|
||||
|
||||
if (x2 >= x1) {
|
||||
dx = x2 - x1;
|
||||
incX = 1;
|
||||
} else {
|
||||
dx = x1 - x2;
|
||||
incX = -1;
|
||||
}
|
||||
|
||||
if (y2 >= y1) {
|
||||
dy = y2 - y1;
|
||||
incY = 1;
|
||||
} else {
|
||||
dy = y1 - y2;
|
||||
incY = -1;
|
||||
}
|
||||
|
||||
x = x1;
|
||||
y = y1;
|
||||
|
||||
if (dx >= dy) {
|
||||
dy <<= 1;
|
||||
balance = dy - dx;
|
||||
dx <<= 1;
|
||||
while (x != x2) {
|
||||
jlDrawPoint(x, y);
|
||||
if (balance >= 0) {
|
||||
y += incY;
|
||||
balance -= dx;
|
||||
}
|
||||
balance += dy;
|
||||
x += incX;
|
||||
}
|
||||
jlDrawPoint(x, y);
|
||||
} else {
|
||||
dx <<= 1;
|
||||
balance = dx - dy;
|
||||
dy <<= 1;
|
||||
while (y != y2) {
|
||||
jlDrawPoint(x, y);
|
||||
if (balance >= 0) {
|
||||
x += incX;
|
||||
balance -= dy;
|
||||
}
|
||||
balance += dx;
|
||||
y += incY;
|
||||
}
|
||||
jlDrawPoint(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void jlKeyWaitForAny(void) {
|
||||
while (!jlKeyPressed() && !jlUtilMustExit()) ;
|
||||
jlKeyRead();
|
||||
while (jlKeyPressed() && !jlUtilMustExit()) ;
|
||||
}
|
||||
|
||||
|
||||
void jlPaletteDefault(void) {
|
||||
byte i;
|
||||
// Set palette.
|
||||
_jlDefaultPalette[ 0].r = 0; _jlDefaultPalette[ 0].g = 0; _jlDefaultPalette[ 0].b = 0; // 000000 Black
|
||||
_jlDefaultPalette[ 1].r = 0; _jlDefaultPalette[ 1].g = 0; _jlDefaultPalette[ 1].b = 10; // 0000AA Blue
|
||||
_jlDefaultPalette[ 2].r = 0; _jlDefaultPalette[ 2].g = 10; _jlDefaultPalette[ 2].b = 0; // 00AA00 Green
|
||||
_jlDefaultPalette[ 3].r = 0; _jlDefaultPalette[ 3].g = 10; _jlDefaultPalette[ 3].b = 10; // 00AAAA Cyan
|
||||
_jlDefaultPalette[ 4].r = 10; _jlDefaultPalette[ 4].g = 0; _jlDefaultPalette[ 4].b = 0; // AA0000 Red
|
||||
_jlDefaultPalette[ 5].r = 10; _jlDefaultPalette[ 5].g = 0; _jlDefaultPalette[ 5].b = 10; // AA00AA Magenta
|
||||
_jlDefaultPalette[ 6].r = 10; _jlDefaultPalette[ 6].g = 5; _jlDefaultPalette[ 6].b = 0; // AA5500 Brown
|
||||
_jlDefaultPalette[ 7].r = 10; _jlDefaultPalette[ 7].g = 10; _jlDefaultPalette[ 7].b = 10; // AAAAAA Light Gray
|
||||
_jlDefaultPalette[ 8].r = 5; _jlDefaultPalette[ 8].g = 5; _jlDefaultPalette[ 8].b = 5; // 555555 Dark Gray
|
||||
_jlDefaultPalette[ 9].r = 5; _jlDefaultPalette[ 9].g = 5; _jlDefaultPalette[ 9].b = 15; // 5555FF Bright Blue
|
||||
_jlDefaultPalette[10].r = 5; _jlDefaultPalette[10].g = 15; _jlDefaultPalette[10].b = 5; // 55FF55 Bright Green
|
||||
_jlDefaultPalette[11].r = 5; _jlDefaultPalette[11].g = 15; _jlDefaultPalette[11].b = 15; // 55FFFF Bright Cyan
|
||||
_jlDefaultPalette[12].r = 15; _jlDefaultPalette[12].g = 5; _jlDefaultPalette[12].b = 5; // FF5555 Bright Red
|
||||
_jlDefaultPalette[13].r = 15; _jlDefaultPalette[13].g = 5; _jlDefaultPalette[13].b = 15; // FF55FF Bright Magenta
|
||||
_jlDefaultPalette[14].r = 15; _jlDefaultPalette[14].g = 15; _jlDefaultPalette[14].b = 5; // FFFF55 Bright Yellow
|
||||
_jlDefaultPalette[15].r = 15; _jlDefaultPalette[15].g = 15; _jlDefaultPalette[15].b = 15; // FFFFFF White
|
||||
for (i=0; i<16; i++) {
|
||||
jlPaletteSet(i, _jlDefaultPalette[i].r, _jlDefaultPalette[i].g, _jlDefaultPalette[i].b);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool _jlStaCopy(jlStaT *source, jlStaT **target) {
|
||||
jlStaT *t = NULL;
|
||||
// Are we copying into a new image?
|
||||
if (*target == NULL) {
|
||||
t = (jlStaT *)jlMalloc(sizeof(jlStaT));
|
||||
if (t == NULL) {
|
||||
return false;
|
||||
}
|
||||
*target = t;
|
||||
}
|
||||
t = (jlStaT *)*target;
|
||||
memcpy(*target, source, sizeof(jlStaT));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void jlStaFree(jlStaT *sta) {
|
||||
if (sta != NULL) {
|
||||
jlFree(sta);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool _jlStaLoad(jlStaT **sta, char *filename) {
|
||||
bool result = false;
|
||||
jlStaT *s = NULL;
|
||||
FILE *f = NULL;
|
||||
|
||||
// Are we loading into a new image?
|
||||
if (*sta == NULL) {
|
||||
s = (jlStaT *)jlMalloc(sizeof(jlStaT));
|
||||
if (s == NULL) {
|
||||
return result;
|
||||
}
|
||||
*sta = s;
|
||||
}
|
||||
s = (jlStaT *)*sta;
|
||||
// Load into it.
|
||||
f = fopen(filename, "rb");
|
||||
if (f != NULL) {
|
||||
if (fread(s, sizeof(jlStaT), 1, f) > 0) {
|
||||
// Is this a valid image file?
|
||||
if ((s->id[0] == 'S') && (s->id[1] == 'T') && (s->id[2] == 'A') && (s->version <= 0)) {
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool jlStaSave(jlStaT *sta, char *filename) {
|
||||
bool result = false;
|
||||
FILE *f;
|
||||
|
||||
f = fopen(filename, "wb");
|
||||
if (f != NULL) {
|
||||
if (fwrite(sta, sizeof(jlStaT), 1, f) > 0) {
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
__attribute__((__format__ (__printf__, 1, 0)))
|
||||
void jlUtilDie(const char *why, ...) {
|
||||
#ifdef JOEY_DEBUG
|
||||
int i;
|
||||
FILE *f = NULL;
|
||||
char msg[80]; // Very short messages (screen width). Be careful!
|
||||
va_list va;
|
||||
|
||||
va_start(va, why);
|
||||
vsprintf(msg, why, va);
|
||||
va_end(va);
|
||||
|
||||
f = fopen("JLSTATS", "wt");
|
||||
if (f != NULL) {
|
||||
fprintf(f, "JoeyLib Statistics\n\n");
|
||||
fprintf(f, " Allocations: %ld\n", _jlTotalAllocations);
|
||||
fprintf(f, " Frees: %ld\n", _jlTotalFrees);
|
||||
fprintf(f, " Most Used: %ldM (%ldK) (%ld bytes)\n", _jlHighWaterMark / 1048576, _jlHighWaterMark / 1024, _jlHighWaterMark);
|
||||
fprintf(f, " Blocks Used: %ld (of %ld)\n", _jlBlocksNeeded, (long)JOEY_MEM_BLOCKS);
|
||||
if (_jlTotalAllocations > _jlTotalFrees) {
|
||||
for (i=0; i<JOEY_MEM_BLOCKS; i++) {
|
||||
if (_jlMemoryBlocks[i].addr != NULL) {
|
||||
fprintf(f, "Unfreed Block: %ld bytes, %d @ %s\n", (long int)_jlMemoryBlocks[i].size, _jlMemoryBlocks[i].line, _jlMemoryBlocks[i].file);
|
||||
}
|
||||
}
|
||||
}
|
||||
//fprintf(f, "jlBorderSaved %d %d\n", jlBorderSaved.rtcReserved, jlBorderSaved.border);
|
||||
fprintf(f, "\n%s\n", msg);
|
||||
fclose(f);
|
||||
}
|
||||
#else
|
||||
(void)why;
|
||||
#endif
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
void *_jlUtilStackPop(jlStackT **stack) {
|
||||
void *d = NULL;
|
||||
jlStackT *s;
|
||||
if (*stack != NULL) {
|
||||
s = *stack;
|
||||
d = s->data;
|
||||
*stack = s->previous;
|
||||
jlFree(s);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
void _jlUtilStackPush(jlStackT **stack, void *data) {
|
||||
jlStackT *s = NULL;
|
||||
s = (jlStackT *)jlMalloc(sizeof(jlStackT));
|
||||
s->previous = *stack;
|
||||
s->data = data;
|
||||
*stack = s;
|
||||
}
|
||||
|
||||
|
||||
void jlVecDisplay(jlVecT *vec, int ox, int oy) {
|
||||
int command;
|
||||
int count;
|
||||
int i;
|
||||
int x1;
|
||||
int y1;
|
||||
int x2;
|
||||
int y2;
|
||||
long p = 0;
|
||||
|
||||
while (p < vec->length) {
|
||||
command = vec->data[p++];
|
||||
switch (command) {
|
||||
|
||||
case COMMAND_COLOR:
|
||||
x1 = vec->data[p++];
|
||||
jlDrawColor((byte)x1);
|
||||
break;
|
||||
|
||||
case COMMAND_CLEAR:
|
||||
jlDrawClear();
|
||||
break;
|
||||
|
||||
case COMMAND_PLOT:
|
||||
count = vec->data[p++];
|
||||
for (i=0; i<count; i += 2) {
|
||||
x1 = ox + (int)(vec->data[p++] * VEC_SCALE_UP);
|
||||
y1 = oy + vec->data[p++];
|
||||
jlDrawPoint(x1, y1);
|
||||
}
|
||||
break;
|
||||
|
||||
case COMMAND_LINE:
|
||||
count = vec->data[p++];
|
||||
x1 = ox + (int)(vec->data[p++] * VEC_SCALE_UP);
|
||||
y1 = oy + vec->data[p++];
|
||||
for (i=2; i<count; i += 2) {
|
||||
x2 = ox + (int)(vec->data[p++] * VEC_SCALE_UP);
|
||||
y2 = oy + vec->data[p++];
|
||||
jlDrawLine(x1, y1, x2, y2);
|
||||
x1 = x2;
|
||||
y1 = y2;
|
||||
}
|
||||
break;
|
||||
|
||||
case COMMAND_FILL:
|
||||
count = vec->data[p++];
|
||||
for (i=0; i<count; i += 2) {
|
||||
x1 = ox + (int)(vec->data[p++] * VEC_SCALE_UP);
|
||||
y1 = oy + vec->data[p++];
|
||||
jlDrawFill(x1, y1);
|
||||
}
|
||||
break;
|
||||
|
||||
case COMMAND_PALETTE:
|
||||
count = vec->data[p++];
|
||||
for (i=0; i<count; i += 4) {
|
||||
x1 = vec->data[p++];
|
||||
y1 = vec->data[p++];
|
||||
x2 = vec->data[p++];
|
||||
y2 = vec->data[p++];
|
||||
jlPaletteSet((byte)x1,(byte)y1, (byte)x2, (byte)y2);
|
||||
}
|
||||
break;
|
||||
|
||||
case COMMAND_RESET:
|
||||
jlPaletteDefault();
|
||||
break;
|
||||
|
||||
case COMMAND_HBOX:
|
||||
count = vec->data[p++];
|
||||
for (i=0; i<count; i += 4) {
|
||||
x1 = ox + (int)(vec->data[p++] * VEC_SCALE_UP);
|
||||
y1 = oy + vec->data[p++];
|
||||
x2 = ox + (int)(vec->data[p++] * VEC_SCALE_UP);
|
||||
y2 = oy + vec->data[p++];
|
||||
jlDrawBox(x1, y1, x2, y2);
|
||||
}
|
||||
break;
|
||||
|
||||
case COMMAND_FBOX:
|
||||
count = vec->data[p++];
|
||||
for (i=0; i<count; i += 4) {
|
||||
x1 = ox + (int)(vec->data[p++] * VEC_SCALE_UP);
|
||||
y1 = oy + vec->data[p++];
|
||||
x2 = ox + (int)(vec->data[p++] * VEC_SCALE_UP);
|
||||
y2 = oy + vec->data[p++];
|
||||
jlDrawBoxFilled(x1, y1, x2, y2);
|
||||
}
|
||||
break;
|
||||
|
||||
case COMMAND_FILLTO:
|
||||
count = vec->data[p++];
|
||||
for (i=0; i<count; i += 2) {
|
||||
x1 = ox + (int)(vec->data[p++] * VEC_SCALE_UP);
|
||||
y1 = oy + vec->data[p++];
|
||||
x2 =vec->data[p++];
|
||||
jlDrawFillTo(x1, y1, (byte)x2);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
} // switch
|
||||
} // while
|
||||
}
|
||||
|
||||
|
||||
void jlVecFree(jlVecT *vec) {
|
||||
if (vec != NULL) {
|
||||
jlFree(vec->data);
|
||||
jlFree(vec);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool _jlVecLoad(jlVecT **vec, char *filename) {
|
||||
bool result = false;
|
||||
jlVecT *v = NULL;
|
||||
FILE *f = NULL;
|
||||
long size;
|
||||
|
||||
// Are we loading into a new image?
|
||||
if (*vec != NULL) {
|
||||
jlVecFree(*vec);
|
||||
}
|
||||
v = (jlVecT *)jlMalloc(sizeof(jlVecT));
|
||||
if (v == NULL) {
|
||||
return result;
|
||||
}
|
||||
*vec = v;
|
||||
v = (jlVecT *)*vec;
|
||||
// Load into it.
|
||||
f = fopen(filename, "rb");
|
||||
if (f != NULL) {
|
||||
fseek(f, 0, SEEK_END);
|
||||
size = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
v->length = (unsigned int)((unsigned long)size - (sizeof(char) * 3) + (sizeof(byte)));
|
||||
// Load header.
|
||||
v->id[0] = (char)fgetc(f);
|
||||
v->id[1] = (char)fgetc(f);
|
||||
v->id[2] = (char)fgetc(f);
|
||||
v->version = (byte)fgetc(f);
|
||||
// Is this a valid image file?
|
||||
if ((v->id[0] == 'V') && (v->id[1] == 'E') && (v->id[2] == 'C') && (v->version <= 0)) {
|
||||
v->data = (byte *)jlMalloc(sizeof(byte) * v->length);
|
||||
if (fread(v->data, sizeof(byte), v->length, f) > 0) {
|
||||
result = true;
|
||||
} else {
|
||||
jlFree(v->data);
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
return result;
|
||||
}
|
261
src/joey.h
Normal file
261
src/joey.h
Normal file
|
@ -0,0 +1,261 @@
|
|||
/*
|
||||
* JoeyLib
|
||||
* Copyright (C) 2018 Scott Duensing <scott@kangaroopunch.com>
|
||||
*
|
||||
* This software is provided 'as-is', without any express 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 H_JOEY_
|
||||
#define H_JOEY_
|
||||
|
||||
#define JOEY_DEBUG
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#ifndef bool
|
||||
#define bool unsigned char
|
||||
#define true 1
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
#define byte unsigned char
|
||||
|
||||
|
||||
extern byte _jlDrawColor;
|
||||
extern byte _jlDrawColorNibbles;
|
||||
extern byte _jlBorderColor;
|
||||
|
||||
|
||||
enum _jlBorderColorsE {
|
||||
BORDER_BLACK = 0,
|
||||
BORDER_DEEP_RED = 1,
|
||||
BORDER_DEEP_BLUE = 2,
|
||||
BORDER_PURPLE = 3,
|
||||
BORDER_DARK_GREEN = 4,
|
||||
BORDER_DARK_GRAY = 5,
|
||||
BORDER_MEDIUM_BLUE = 6,
|
||||
BORDER_LIGHT_BLUE = 7,
|
||||
BORDER_BROWN = 8,
|
||||
BORDER_ORANGE = 9,
|
||||
BORDER_LIGHT_GRAY = 10,
|
||||
BORDER_PINK = 11,
|
||||
BORDER_GREEN = 12,
|
||||
BORDER_YELLOW = 13,
|
||||
BORDER_AQUAMARINE = 14,
|
||||
BORDER_WHITE = 15
|
||||
};
|
||||
typedef enum _jlBorderColorsE jlBorderColorsE;
|
||||
|
||||
|
||||
typedef struct {
|
||||
byte b : 4;
|
||||
byte g : 4;
|
||||
byte r : 4;
|
||||
byte reserved : 4;
|
||||
} jlColorT;
|
||||
|
||||
typedef struct {
|
||||
byte l : 4;
|
||||
byte r : 4;
|
||||
} jlPixelPairT;
|
||||
|
||||
typedef struct {
|
||||
void *data;
|
||||
int channel;
|
||||
} jlSoundT;
|
||||
|
||||
typedef struct {
|
||||
char id[3];
|
||||
byte version;
|
||||
jlColorT palette[16]; // 4 bits reserved, 4 bits red, 4 green, 4 blue
|
||||
jlPixelPairT pixels[32000]; // 320x200, 4 bits per pixel
|
||||
} jlStaT;
|
||||
|
||||
typedef struct _jlStackS {
|
||||
struct _jlStackS *previous;
|
||||
void *data;
|
||||
} jlStackT;
|
||||
|
||||
typedef struct {
|
||||
char id[3];
|
||||
byte version;
|
||||
unsigned int length;
|
||||
byte *data;
|
||||
} jlVecT;
|
||||
|
||||
|
||||
// Memory Management
|
||||
#ifdef JOEY_DEBUG
|
||||
|
||||
#define JOEY_MEM_BLOCKS 64
|
||||
|
||||
typedef struct {
|
||||
void *addr;
|
||||
char *file;
|
||||
size_t size;
|
||||
int line;
|
||||
} jlMemoryBlockT;
|
||||
|
||||
#define jlFree(p) _jlFree((void **)&(p))
|
||||
void _jlFree(void **pointer);
|
||||
|
||||
#define jlMalloc(s) _jlMalloc(s, __LINE__, __FILE__)
|
||||
void *_jlMalloc(size_t size, int line, char *file);
|
||||
|
||||
#define jlRealloc(p, s) _jlRealloc(p, s)
|
||||
void *_jlRealloc(void *pointer, size_t size);
|
||||
|
||||
#else
|
||||
|
||||
#define jlFree free
|
||||
#define jlMalloc malloc
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// Determine platform and settings
|
||||
#ifdef __linux__
|
||||
|
||||
#define JOEY_LINUX
|
||||
#define JOEY_PC
|
||||
#define JOEY_LITLE_ENDIAN
|
||||
#define segment(x)
|
||||
|
||||
#elif _WIN32
|
||||
|
||||
#define JOEY_WINDOWS
|
||||
#define JOEY_PC
|
||||
#define JOEY_LITLE_ENDIAN
|
||||
#define segment(x)
|
||||
|
||||
#elif __APPLE__
|
||||
|
||||
#define JOEY_MACOS
|
||||
#define JOEY_PC
|
||||
#define JOEY_LITLE_ENDIAN
|
||||
#define segment(x)
|
||||
|
||||
#elif __ORCAC__
|
||||
|
||||
#define JOEY_IIGS
|
||||
#define JOEY_LITLE_ENDIAN
|
||||
#define __attribute__(x)
|
||||
#ifdef JOEY_LIBRARY
|
||||
#pragma noroot
|
||||
segment "joeylib";
|
||||
#endif
|
||||
#pragma memorymodel 1
|
||||
#pragma optimize -1
|
||||
#pragma lint -1
|
||||
#pragma debug 0
|
||||
|
||||
#elif AMIGA
|
||||
|
||||
#define JOEY_AMIGA
|
||||
#define JOEY_BIG_ENDIAN
|
||||
#define __attribute__(x)
|
||||
#define segment(x)
|
||||
|
||||
#else
|
||||
|
||||
#define JOEY_ST
|
||||
#define JOEY_BIG_ENDIAN
|
||||
#define __attribute__(x)
|
||||
#define segment(x)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
void jlDisplayBorder(jlBorderColorsE color);
|
||||
void jlDisplayPresent(void);
|
||||
void jlDrawBlit8x8(jlStaT *sta, int cx1, int cy1, int cx2, int cy2);
|
||||
void jlDrawBox(int x1, int y1, int x2, int y2);
|
||||
void jlDrawBoxFilled(int x1, int y1, int x2, int y2);
|
||||
void jlDrawCircle(int x, int y, int radius);
|
||||
void jlDrawClear(void);
|
||||
void jlDrawColor(byte index);
|
||||
void jlDrawEllipse(int x1, int y1, int x2, int y2);
|
||||
void jlDrawFill(int x, int y);
|
||||
void jlDrawFillTo(int x, int y, byte color);
|
||||
byte jlDrawGetPixel(int x, int y);
|
||||
void jlDrawLine(int x1, int y1, int x2, int y2);
|
||||
void jlDrawPoint(int x, int y);
|
||||
int jlGameGetAxis(byte which);
|
||||
bool jlGameGetButton(byte which);
|
||||
bool jlKeyPressed(void);
|
||||
char jlKeyRead(void);
|
||||
void jlKeyWaitForAny(void);
|
||||
void jlPaletteDefault(void);
|
||||
void jlPaletteSet(byte index, byte r, byte g, byte b);
|
||||
void jlSoundFree(jlSoundT *sound);
|
||||
bool jlSoundIsPlaying(jlSoundT *sound);
|
||||
#define jlSoundLoad(sound, filename) _jlSoundLoad((jlSoundT **)&(sound), filename) // Syntatic Sugar
|
||||
bool _jlSoundLoad(jlSoundT **sound, char *filename);
|
||||
void jlSoundMusicContinue(void);
|
||||
bool jlSoundMusicIsPlaying(void);
|
||||
void jlSoundMusicPause(void);
|
||||
void jlSoundMusicPlay(char *name);
|
||||
void jlSoundMusicStop(void);
|
||||
void jlSoundPlay(jlSoundT *sound);
|
||||
#define jlStaCopy(source, target) _jlStaCopy(source, (jlStaT **)&(target)) // Syntatic Sugar
|
||||
bool _jlStaCopy(jlStaT *source, jlStaT **target);
|
||||
#define jlStaCreate(sta) _jlStaCreate((jlStaT **)&(sta)) // Syntatic Sugar
|
||||
bool _jlStaCreate(jlStaT **sta);
|
||||
void jlStaDisplay(jlStaT *sta);
|
||||
void jlStaFree(jlStaT *sta);
|
||||
#define jlStaLoad(sta, filename) _jlStaLoad((jlStaT **)&(sta), filename) // Syntatic Sugar
|
||||
bool _jlStaLoad(jlStaT **sta, char *filename);
|
||||
bool jlStaSave(jlStaT *sta, char *filename);
|
||||
void jlUtilDie(const char *why, ...) __attribute__((noreturn));
|
||||
void jlUtilIdle(void);
|
||||
#define jlUtilIsOdd(x) (((x & 1) == 1) ? true:false)
|
||||
bool jlUtilMustExit(void);
|
||||
void jlUtilShutdown(void) __attribute__((noreturn));
|
||||
#define jlUtilStackPop(stack) _jlUtilStackPop((jlStackT **)&(stack)) // Syntatic Sugar
|
||||
void *_jlUtilStackPop(jlStackT **stack);
|
||||
#define jlUtilStackPush(stack, data) _jlUtilStackPush((jlStackT **)&(stack), data) // Syntatic Sugar
|
||||
void _jlUtilStackPush(jlStackT **stack, void *data);
|
||||
void jlUtilStartup(char *appName);
|
||||
unsigned int jlUtilTimer(void);
|
||||
void jlVecDisplay(jlVecT *vec, int x, int y);
|
||||
void jlVecFree(jlVecT *vec);
|
||||
#define jlVecLoad(vec, filename) _jlVecLoad((jlVecT **)&(vec), filename) // Syntatic Sugar
|
||||
bool _jlVecLoad(jlVecT **vec, char *filename);
|
||||
|
||||
|
||||
#ifdef JOEY_IIGS
|
||||
// Inlined functions - asm code
|
||||
extern void asmB88(byte *p, int cx1, int cy1, int cx2, int cy2);
|
||||
extern void asmPoint(int color, int x, int y);
|
||||
extern int asmGetPoint(int x, int y);
|
||||
extern unsigned int asmGetVbl(void);
|
||||
|
||||
// Inlined functions
|
||||
#define jlDrawBlit8x8(sta, cx1, cy1, cx2, cy2) asmB88((byte *)sta->pixels, cx1, cy1, cx2, cy2);
|
||||
#define jlDrawGetPixel(x, y) asmGetPoint(x, y)
|
||||
#define jlDrawPoint(x, y) asmPoint(_jlDrawColorNibbles, x, y)
|
||||
#define jlUtilTimer asmGetVbl
|
||||
|
||||
#ifdef JOEY_DEBUG
|
||||
void _jlDebugBorder(jlBorderColorsE color);
|
||||
#endif
|
||||
#endif // JOEY_IIGS
|
||||
|
||||
|
||||
#endif // H_JOEY_
|
BIN
src/kanga.sta
Normal file
BIN
src/kanga.sta
Normal file
Binary file not shown.
BIN
src/music.mod
Normal file
BIN
src/music.mod
Normal file
Binary file not shown.
95
src/stddclmr.h
Normal file
95
src/stddclmr.h
Normal file
|
@ -0,0 +1,95 @@
|
|||
#ifndef STDDCLMR_H
|
||||
#define STDDCLMR_H
|
||||
|
||||
/*
|
||||
Action figures sold separately. Add toner. All models over 18 years of age.
|
||||
All rights reserved. Allow four to six weeks for delivery. An equal
|
||||
opportunity employer. Any resemblance to actual persons, living or dead, is
|
||||
unintentional and purely coincidental. Apply only to affected area. Approved
|
||||
for veterans. As seen on TV. At participating locations only. Avoid contact
|
||||
with mucous membranes. Avoid contact with skin. Avoid extreme temperatures
|
||||
and store in a cool dry place. Batteries not included. Be sure each item is
|
||||
properly endorsed. Beware of dog. Booths for two or more. Breaking seal
|
||||
constitutes acceptance of agreement. Call toll free number before digging.
|
||||
Caveat emptor. Check here if tax deductible. Close cover before striking
|
||||
Colors may fade. Contains a substantial amount of non-tobacco ingredients.
|
||||
Contents may settle during shipment. Contestants have been briefed on some
|
||||
questions before the show. Copyright 1995 Joker's Wild. Disclaimer does
|
||||
not cover hurricane, lightning, tornado, tsunami, volcanic eruption,
|
||||
earthquake, flood, and other Acts of God, misuse, neglect, unauthorized
|
||||
repair, damage from improper installation, broken antenna or marred cabinet,
|
||||
incorrect line voltage, missing or altered serial numbers, sonic boom
|
||||
vibrations, electromagnetic radiation from nuclear blasts, customer
|
||||
adjustments that are not covered in the joke list, and incidents owing to
|
||||
airplane crash, ship sinking, motor vehicle accidents, leaky roof, broken
|
||||
glass, falling rocks, mud slides, forest fire, flying projectiles, or
|
||||
dropping the item. Do not bend, fold, mutilate, or spindle. Do not place
|
||||
near flammable or magnetic source. Do not puncture, incinerate, or store
|
||||
above 120 degrees Fahrenheit. Do not stamp. Use other side for additional
|
||||
listings. Do not use while operating a motor vehicle or heavy equipment. Do
|
||||
not write below this line. Documents are provided "as is" without any
|
||||
warranties expressed or implied. Don't quote me on anything. Don't quote me
|
||||
on that. Driver does not carry cash. Drop in any mailbox. Edited for
|
||||
television. Employees and their families are not eligible. Falling rock.
|
||||
First pull up, then pull down. Flames redirected to /dev/null. For a
|
||||
limited time only. For external use only. For off-road use only. For office
|
||||
use only. For recreational use only. Do not disturb. Freshest if eaten
|
||||
before date on carton. Hand wash only, tumble dry on low heat. If a rash,
|
||||
redness, irritation, or swelling develops, discontinue use. If condition
|
||||
persists, consult your physician. If defects are discovered, do not attempt
|
||||
to fix them yourself, but return to an authorized service center. If
|
||||
ingested, do not induce vomiting, if symptoms persist, consult a doctor.
|
||||
Keep away from open flames and avoid inhaling fumes. Keep away from
|
||||
sunlight, pets, and small children. Keep cool; process promptly. Limit
|
||||
one-per-family please. Limited time offer, call now to ensure prompt
|
||||
delivery. List at least two alternate dates. List each check separately by
|
||||
bank number. List was current at time of printing. Lost ticket pays maximum
|
||||
rate. May be too intense for some viewers. Must be 18 to enter. No Canadian
|
||||
coins. No alcohol, dogs or horses. No anchovies unless otherwise specified.
|
||||
No animals were harmed in the production of these documents. No money down.
|
||||
No other warranty expressed or implied. No passes accepted for this
|
||||
engagement. No postage necessary if mailed in the United States. No
|
||||
preservatives added. No purchase necessary. No salt, MSG, artificial color
|
||||
or flavor added. No shoes, no shirt, no service, no kidding. No solicitors.
|
||||
No substitutions allowed. No transfers issued until the bus comes to a
|
||||
complete stop. No user-serviceable parts inside. Not affiliated with the
|
||||
American Red Cross. Not liable for damages due to use or misuse. Not
|
||||
recommended for children. Not responsible for direct, indirect, incidental
|
||||
or consequential damages resulting from any defect, error or failure to
|
||||
perform. Not the Beatles. Objects in mirror may be closer than they appear.
|
||||
One size fits all. Many suitcases look alike. Other copyright laws for
|
||||
specific entries apply wherever noted. Other restrictions may apply. Package
|
||||
sold by weight, not volume. Parental advisory - explicit lyrics. Penalty for
|
||||
private use. Place stamp here. Please remain seated until the ride has come
|
||||
to a complete stop. Possible penalties for early withdrawal. Post office will
|
||||
not deliver without postage. Postage will be paid by addressee. Prerecorded
|
||||
for this time zone. Price does not include taxes. Processed at location
|
||||
stamped in code at top of carton. Quantities are limited while supplies last.
|
||||
Read at your own risk. Record additional transactions on back of previous
|
||||
stub. Replace with same type. Reproduction strictly prohibited. Restaurant
|
||||
package, not for resale. Return to sender, no forwarding order on file,
|
||||
unable to forward. Safety goggles may be required during use. Sanitized for
|
||||
your protection. Sealed for your protection, do not use if the safety seal is
|
||||
broken. See label for sequence. Shading within a garment may occur. Sign here
|
||||
without admitting guilt. Simulated picture. Slightly enlarged to show detail.
|
||||
Slightly higher west of the Rockies. Slippery when wet. Smoking these may be
|
||||
hazardous to your health. Some assembly required. Some equipment shown is
|
||||
optional. Some of the trademarks mentioned in this product appear for
|
||||
identification purposes only. Subject to FCC approval. Subject to change
|
||||
without notice. Substantial penalty for early withdrawal. Text may contain
|
||||
material some readers may find objectionable, parental guidance is advised.
|
||||
Text used in these documents is made from 100% recycled electrons and magnetic
|
||||
particles. These documents do not reflect the thoughts or opinions of either
|
||||
myself, my company, my friends, or my rabbit. This is not an offer to sell
|
||||
securities. This offer is void where prohibited, taxed, or otherwise
|
||||
restricted. This product is meant for educational purposes only. Times
|
||||
approximate. Unix is a registered trademark of AT&T. Use only as directed. Use
|
||||
only in a well-ventilated are. User assumes full liabilities. Void where
|
||||
prohibited. We have sent the forms which seem right for you. You must be
|
||||
present to win. You need not be present to win. Your canceled check is your
|
||||
receipt. Your mileage may vary. I didn't do it. You can't prove anything.
|
||||
|
||||
This supersedes all previous notices.
|
||||
*/
|
||||
|
||||
#endif // STDDCLMR_H
|
87
src/test.c
Normal file
87
src/test.c
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* JoeyLib
|
||||
* Copyright (C) 2018 Scott Duensing <scott@kangaroopunch.com>
|
||||
*
|
||||
* This software is provided 'as-is', without any express 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
#include "joey.h"
|
||||
|
||||
|
||||
#ifdef JOEY_IIGS
|
||||
segment "testapp";
|
||||
#endif
|
||||
|
||||
|
||||
// Font hacking!
|
||||
__attribute__((__format__ (__printf__, 4, 0)))
|
||||
void printAt(jlStaT *font, int cx, int cy, const char *what, ...) {
|
||||
int x;
|
||||
int y;
|
||||
int counter;
|
||||
char msg[40]; // Very short messages (screen width). Be careful!
|
||||
va_list va;
|
||||
|
||||
va_start(va, what);
|
||||
vsprintf(msg, what, va);
|
||||
va_end(va);
|
||||
|
||||
for (counter=0; counter<(int)strlen(msg); counter++) {
|
||||
y = (msg[counter] - ' ') / 40;
|
||||
x = (msg[counter] - ' ') % 40;
|
||||
jlDrawBlit8x8(font, x, y, counter + cx, cy);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(void) {
|
||||
|
||||
jlStaT *kanga = NULL;
|
||||
jlStaT *font = NULL;
|
||||
|
||||
jlUtilStartup("JoeyLib Test");
|
||||
|
||||
jlStaLoad(kanga, "kanga.sta");
|
||||
jlStaLoad(font, "font.sta");
|
||||
|
||||
jlStaDisplay(kanga);
|
||||
jlDrawColor(1);
|
||||
jlDrawBox(0, 0, 319, 199);
|
||||
|
||||
jlSoundMusicPlay("music");
|
||||
|
||||
jlPaletteSet(15, 15, 15, 15);
|
||||
while (!jlKeyPressed()) {
|
||||
printAt(font, 1, 20, "T = %d ", jlUtilTimer());
|
||||
jlDisplayPresent();
|
||||
}
|
||||
jlKeyRead();
|
||||
|
||||
jlSoundMusicStop();
|
||||
|
||||
jlStaFree(font);
|
||||
jlStaFree(kanga);
|
||||
|
||||
jlUtilShutdown();
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue