A follow up from the PETSCII post here – this now uses the tilemap, palette changing, NextZXOS Browser to load PRG/PSC files and can run a slide show.
Credit to the many artists that produce amazing PETSCII work demo’d here including:
PETSCII logo [LMan]
Marq: Whom Are You Going to Call?
Marq: Calaveritas
Dr. TerrorZ: PETSCII Tracing
Dr. TerrorZ: Electric Circus
Rexbeng: Undo
Manu: Rabbit on Acid Trip
Electric: SixShots
Electric: Coltrane
Redcrab: It Ain’t Pretty!
Redcrab: Datagubbe
Redcrab: Ernie
iLKke: Breakfast of Champions
C64 PETSCII by Mermaid.
'#!v
'#!sna "h:\mouse2.sna" -a
'!bin "h:\nextscii\test.bin" -a
'#!noemu
' nextscii viwer by David Saphier / emook2019
' https://zxnext.uk/nextbuild/nextscii/
#include <nextlib.bas>
NextReg(8,$fe) ' no contention
NextReg(7,2) ' 14mhz
NextReg($40,0) ' palette index 0
NextReg($41,$0) ' set black
NextReg($4A,0) ' Transparency 0
NextReg($1B,0) ' x1 tilemap clip
NextReg($1B,159) ' x2
NextReg($1B,0) ' y1
NextReg($1B,255) ' y2
' (R/W) 0x6B (107) => Tilemap Control
' bit 7 = 1 to enable the tilemap
' bit 6 = 0 for 40x32, 1 for 80x32
' bit 5 = 1 to eliminate the attribute entry in the tilemap
' bit 4 = palette select
' bits 3-2 = Reserved set to 0
' bit 1 = 1 to activate 512 tile mode
' bit 0 = 1 to force tilemap on top of ULA
' 76543210
NextReg($6B,%10000001) ' tilemap on & on top of ULA, 80x32
NextReg($6E,$40) ' (R/W) 0x6E (110) => Tilemap Base Address 0 = $4000
NextReg($6F,$60) ' (R/W) 0x6F (111) => Tile Definitions Base Address
NextReg($43,%00110000)
dim r,g,b,fc as ubyte
dim r9,g9,b9 as uinteger
dim result as ubyte
dim v as ubyte
dim f,x,pcount as uinteger
dim tindex,alltext,tcount,peekstringcount,Memory as uinteger
dim temp$,ext$,tx$ as string
dim xr,xy,vv,xx,yy,k,car,st,subcar,cc,cof,tma,paloff,palcols,prg,col,yr,offsetload,size,prg2,nbrsplits as ubyte
dim count,c as ubyte
dim splitted$ as string =" "
dim z$ as string =" "
dim text$ as string =" "
dim type$ as string =" "
dim fname$ as string =" "
paloff=0 : pcount = 0
declare function SplitString(byval s$ as string,byval split$ as string,byval index as ubyte) as string
declare function PeekString(Memory as uinteger) as string
LoadSD("UC.spr",$6000,8192,0) ' our tile map bitmap 4bit 512 blocks
Zx7Unpack(@infoscreen,$b400)
Reload:
tma=1
border 0 : paper 0 : ink 0: cls
DoScreen()
SetPalette(1)
pause 0
nbrsplits=1
LoadSD("list.txt",$b000,1024,0)
if peek($b000)<>0
' rolling
text$=PeekString($b000)
do
DO
splitted$=SplitString(text$,chr($0a),nbrsplits)
type$=SplitString(splitted$,".",2)
NextReg($6B,%00000000) ' tilemap off
type2$=type$
nbrsplits=nbrsplits+1
'BBREAK
if splitted$(0)=chr $0a
splitted$=splitted$ (1 to )
endif
if type2$( to 2)="PRG"
fname$=splitted$
LoadSD(fname$( to ),$b400,1,$19)
LoadSD(fname$( to ),$b401,1,$1E)
LoadSD(fname$( to ),$b402,2002,98)
elseif type2$( to 2)="PSC"
fname$=splitted$
LoadSD(fname$( to ),$b400,2002,0)
border 1
endif
CLS : border 0
NextReg($6B,%00000000) ' tilemap off
DoScreen()
SetPalette(palette)
NextReg($6B,%10000001) ' tilemap on
do
key$=inkey$
if key$="p"
palette=palette+1 Band 7
SetPalette(palette)
updatemap(0,0,48+palette,2)
elseif key$="o"
palette=palette-1 BAND 7
SetPalette(palette)
updatemap(0,0,48+palette,2)
elseif key$="e"
NextReg($6B,%00000000)
goto finish
elseif key$="b"
NextReg($6B,%00000000)
exittobrowser=1
exit DO
elseif key$<>""
exitloop=1
endif
pause 5
loop until exitloop=1
exitloop=0
if exittobrowser=1 : exit do : endif
loop until splitted$(to 2)="END"
nbrsplits=1
if exittobrowser=1 : exit do : endif
loop
endif
do
pause 1
key$=inkey$
if key$="p"
palette=palette+1 Band 7
SetPalette(palette)
updatemap(0,0,48+palette,2)
elseif key$="o"
palette=palette-1 BAND 7
SetPalette(palette)
updatemap(0,0,48+palette,2)
elseif key$="e"
NextReg($6B,%00000000)
Goto finish
elseif key$<>""
cls
Browser("Choose a .PRG or .PSC from PetMate","PRG")
s$=""
for x=0 to 13
c=peek (@filebuffer+x) : if c=255 : size=x-1 : x = 13 :ELSE s$=s$+chr c : endif :
next
if peek(@filebuffer+size)=code "G"
LoadSD(s$,$b400,1,$19)
LoadSD(s$,$b401,1,$1E)
LoadSD(s$,$b402,2002,98)
else
LoadSD(s$,$b400,2002,0)
endif
CLS : border 0
DoScreen()
SetPalette(palette)
NextReg($6B,%10000001) ' tilemap on
elseif key$="m" ' flips tilemap not used
if tma=0
NextReg($6F,$60)
tma =1
else
NextReg($6F,$90)
tma=0
endif
endif
while inkey$<>""
pause 1
wend
loop
SUB SetPalette(palette as ubyte)
pcount=cast(uinteger,palette)*64
bordercol=peek($b400)
papercol=peek($b401)
borderindex=@Palette+2+(cast(uinteger,bordercol)*4)
paperindex=@Palette+2+(cast(uinteger,papercol)*4)
NextRegA($40,0)
NextRegA($44,peek(paperindex))
NextRegA($44,0)
NextRegA($44,0)
NextRegA($44,0)
NextRegA($40,paloff+4)
for paltot=0 to 15
NextRegA($44,peek(paperindex))
NextRegA($44,0)
prg=peek(@Palette+cast(uinteger,palcols+2)+pcount)
prg2=peek(@Palette+cast(uinteger,palcols+3)+pcount)
NextRegA($44,prg)
NextRegA($44,prg2)
pcount=pcount+4
paloff=paloff+16
NextRegA($40,paloff)
next
end sub
sub DoScreen()
asm
ld hl,$4000
ld de,$4001
ld (hl),32
ld bc,3999
ldir
end asm
xr=0 : yr = 0 : car=0
for f=0 to 2000
car=peek($b402+cast(uinteger,f ))
col=peek($b402+cast(uinteger,f )+1000)
updatemap(xr,yr,car,col)
xr=xr+1
if xr > 39 'or k=13
yr=yr+1 : xr=0
endif
if yr=25 then f=2000
next
end sub
sub fastcall updatemap(xx as ubyte, yy as ubyte, vv as ubyte, col as ubyte)
asm
;BREAK
pop bc ; return address
ld hl,$4000+160*2 : add a,a : ADD_HL_A ; add x
; hl = $4000+x
pop de : ld a,e : ld e,80 : MUL_DE
add hl,de : pop af
;cp 95
;jr c,skipme
;BREAK
skipme:
ld (hl),a : inc hl : pop af
SWAPNIB : and %11110000
ld (hl),a
push bc
;BREAK
end asm
end sub
sub Browser(byval temp$ as string,byval ext$ as string)
NextReg($6B,%00000000) ' tilemap on & on top of ULA, 80x32
'for p=0 to 2 : poke @extname+p, code(ext$(p)) : next
for p=0 to len(temp$)-1 : poke @testtext+cast(uinteger,p), code(temp$(p)) : next
poke @testtext+cast(uinteger,p),255
asm
; bits of code by Garry Lancaster from .browser sources
;DW $01DD
IDEBROWSER equ $01ba
LAYER equ $9c
IDEBASIC equ $1c0
; Next Registers
nextregselect equ $243b
nextregaccess equ $253b
nxrturbo equ $07
turbomax equ 2
nxrmmu6 equ $56
nxrmmu7 equ $57
tstack equ $bf00
ld (stackstore),sp
ld sp,tstack
browser2:
BREAK
ld a,$7f ; all capabilities
ld hl,ftbuff ; hl = filetypes
ld de,testtext ; de info at bottom of screen +$FF
exx
pressesq:
ld c,7 ; RAM 7 required for most IDEDOS calls
ld de,$01ba ; IDEBROWSER
;ld a,$7f ; all capabilities
rst $8
defb $94 ; MP3DOS
jp nc,FILERROR
jp z,FILEOK
jp nz,browser2
FILEOK:
;pop de ; get off stack
ld a,4
out (254),a
ld de,filebuffer
jp copyRAM7tode
ret
FILERROR:
ret
copyRAM7tode:
push hl ; save source address
ld bc,nextregselect
ld a,nxrmmu6
out (c),a
inc b
in l,(c) ; L=current MMU6 binding
ld a,7*2+0
out (c),a ; rebind to RAM 7 low
dec b
ld a,nxrmmu7
out (c),a
inc b
in h,(c) ; H=current MMU7 binding
ld a,7*2+1
out (c),a ; rebind to RAM 7 high
ex (sp),hl ; save MMU6/7 bindings, refetch source
ld bc,$ffff ; string len, -1 to exclude terminator
cr7tomainloop:
ld a,(hl) ; copy a byte
inc hl
ld (de),a
inc de
inc bc ; increment string length
inc a
jr nz,cr7tomainloop ; back unless $ff-terminator copied
pop hl
ld a,l
defb $ed,$92,nxrmmu6 ; restore MMU6 binding
ld a,h
defb $ed,$92,nxrmmu7 ; restore MMU7 binding
ld hl,filebuffer
add hl,bc
ld a,$ff
ld (hl),a
jp endout
ftbuff:
defb 4
end asm
extname:
asm
defb "PRG:"
defb 4
defb "PSC:"
defb $ff ; all files
end asm
testtext:
asm
testtext:
Defs 64,32
DB 255
stackstore:
dw 0
endout:
rom3page0:
di
ld bc,32765 ;I/O address of horizontal ROM/RAM switch
ld a,(23388) ;get current switch state
set 4,a ;move left to right (ROM 2 to ROM 3)
and $F8 ;also want RAM page 0
;or 0
;ld a,$10
ld (23388),a ;update the system variable (very important)
out (c),a ;make the switch
rst $20
ld sp,(stackstore)
ei
end asm
end sub
filebuffer:
asm
filebuffer:
db "filename.ext"
db 255
end asm
function PeekString(byval Memory as uinteger) as string
dim tempcar$ as string
peekstringcount=0 :tempcar$=""
while peek(ubyte,Memory+peekstringcount)<>0
tcar=peek(ubyte,Memory+peekstringcount)
'tcar=tcar BAND %01111111
if tcar<>$0a or tcar<>$0d0
tempcar$=tempcar$+chr$(tcar)
endif
peekstringcount=peekstringcount+1
wend
return tempcar$
end function
Function SplitString(s$ as string,split$ as string,byval index as ubyte) as string
'dim outstring$ as string
totlen=len(s$) : spos = 0 : tcount=0 : tindex = 0 : outstring$=""
s$=s$+split$
for alltext=0 to totlen+1
curcar$=s$(alltext)
if curcar$=split$
if tindex+1=index
if spos>0
tcount=spos+1
endif
do
outstring$=outstring$+s$(tcount)
tcount=tcount+1 :
loop until s$(tcount)=split$
alltext=totlen
else
spos=alltext
tindex=tindex+1
endif
endif
next alltext
return outstring$
end function
Palette:
ASM
; my original
db 0,0,0,0 ; 0 black
db 0,0,255,1 ; 1 white
db 0,0,137,0 ; 2 dark red
db 0,0,150,0 ; 3 light blue
db 0,0,138,0 ; 4 magenta
db 0,0,117,0 ; 5 dark green
db 0,0,74,0 ; 6 dark purple
db 0,0,217,0 ; 7 yello
db 0,0,141,0 ; 8 light brown
db 0,0,104,0 ; 9 dark brown
db 0,0,210,0 ; 10 beige / pink
db 0,0,73,0 ; 11 dark grey
db 0,0,146,0 ; 12 medium grey
db 0,0,186,0 ; 13 light green
db 0,0,143,1 ; 14 light purple
db 0,0,182,1 ; 15 light grey
; VICE PALETTE
DB 0,0,0,0
DB 0,0,255,1
DB 0,0,160,1
DB 0,0,63,0
DB 0,0,163,1
DB 0,0,24,0
DB 0,0,34,1
DB 0,0,220,0
DB 0,0,100,0
DB 0,0,168,0
DB 0,0,233,0
DB 0,0,73,0
DB 0,0,109,1
DB 0,0,93,0
DB 0,0,75,1
DB 0,0,182,1
; Community colors
DB 0,0,0,0
DB 0,0,255,1
DB 0,0,164,1
DB 0,0,123,0
DB 0,0,166,1
DB 0,0,89,0
DB 0,0,39,0
DB 0,0,253,0
DB 0,0,100,0
DB 0,0,168,0
DB 0,0,237,1
DB 0,0,73,0
DB 0,0,146,0
DB 0,0,190,0
DB 0,0,111,1
DB 0,0,182,1
; colordore
DB 0,0,0,0
DB 0,0,255,1
DB 0,0,132,1
DB 0,0,123,0
DB 0,0,134,0
DB 0,0,85,0
DB 0,0,38,0
DB 0,0,253,1
DB 0,0,68,0
DB 0,0,136,1
DB 0,0,205,1
DB 0,0,73,0
DB 0,0,109,1
DB 0,0,190,0
DB 0,0,111,1
DB 0,0,182,1
; rgb
incbin ".\data\rgb.bin"
; c64 hq
incbin ".\data\c64hq.bin"
; pepto
incbin ".\data\pepto.bin"
; pepto
incbin ".\data\godot.bin"
end asm
infoscreen:
asm
incbin ".\data\info.psc.zx7"
end asm
finish:
asm
rst 56
end asm