Author Topic: nc200 game  (Read 1725 times)

0 Members and 1 Guest are viewing this topic.

Offline arnoldemu

  • Supporter
  • 6128 Plus
  • *
  • Posts: 5.335
  • Country: gb
    • Unofficial Amstrad WWW Resource
  • Liked: 2261
  • Likes Given: 3478
nc200 game
« on: 20:05, 31 January 14 »
Back in 2011 or so I got a nc200 and I wrote some code towards a game.
The plan was that the game could be loaded from disc and run, and worked within the constraints of the system itself. i.e. it didn't run on pcmcia card (because I never had one).

Here is the code:

Code: [Select]
org &4000

scr_height equ 16*8
scr_width equ 480
scr_width_bytes equ scr_width/8

shift_alloc_size equ (256*2*7)+256

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

start:
ld a,&20
ld (shift_table1+1),a
ld (shift_table2+1),a

ld hl,&6000
ld (scr_base+1),hl

push hl
;; set screen
ld a,h
and %11100000
out (&00),a
pop hl

;; we want to hook into the system interrupt

di
ld a,&40
ld (&b000),a
ld (&10),a

ld hl,&0038
ld de,stored_int
ld bc,3
ldir
ei

;; install our int
di
ld a,&c3
ld hl,our_interrupt
ld (&0038),a
ld (&0039),hl
ei

call cls

;; 2 key ints per frame

call init_scr_addr_table

call init_shift_table

ld h,1
ld l,1
call set_txt_coords
ld hl,message
call print_msg

ld hl,1
ld (xcoord),hl
ld hl,16
ld (ycoord),hl

;;padgetticker can be used to read a counter and perhaps use it to determine if a number of interrupts have happened.
xor a
ld (refresh_flag),a

mainloop:
call wait_refresh
call check_move
call draw_sprite

jp mainloop

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

wait_refresh:
ld a,(refresh_flag)
or a
jr z,wait_refresh
xor a
ld (refresh_flag),a
ret


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

stored_int:
defs 3

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

our_interrupt:
push af
in      a,(&90)            ;; irq
bit     3,a                ;; key scan
jr nz,our_interrupt2

;; key scan has happened
ld a,(counter)
inc a
ld (counter),a
cp 2
jr nz,our_interrupt2
xor a
ld (counter),a

;; 2 100Hz = 50Hz
ld a,1
ld (refresh_flag),a

our_interrupt2:
pop af


;; now we setup for system interrupt
;; this is the startup it does
push af
ld      a,(&b003)
;; and then runs to &003c
jp      &003c

;;---------------------------------------------------------------------------------------
;; 10ms counter (100Hz)
counter:
defb 0
;;---------------------------------------------------------------------------------------

refresh_flag:
defb 0

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

exit:
;; restore int
ld hl,stored_int
ld de,&0038
ld bc,3
di
ldir
ei
ret


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

cls:
ld b,scr_height
cls_loop:
push bc
push de
push hl
ld e,l
ld d,h
inc de
ld (hl),0
ld bc,scr_width_bytes-1
ldir
pop hl
call scr_next_line
pop de
pop bc
djnz cls_loop
ret

check_move:
ld a,3
ld c,%100
call check_key
jp nz,move_up
ld a,4
ld c,%10000
call check_key
jp nz,move_down
ld a,9
ld c,%1000
call check_key
jp nz,move_right
ld a,9
ld c,%1000000
call check_key
jp nz,move_left
ret

;;---------------------------------------------------------------------------------------
;; A = line
;; C = mask
check_key:
ld hl,(&b0e6)                    ;; keyboard state filled in by OS
add a,l
ld l,a
ld a,h
adc a,0
ld h,a
ld a,(hl)
and c
ret
;;---------------------------------------------------------------------------------------


move_left:
ld hl,(xcoord)
ld a,h
or l
ret z
dec hl
ld (xcoord),hl
ret
;;---------------------------------------------------------------------------------------

move_right:
ld hl,(xcoord)
ld bc,scr_width-16
or a
sbc hl,bc
ret p
ld hl,(xcoord)
inc hl
ld (xcoord),hl
ret
;;---------------------------------------------------------------------------------------

move_up:
ld hl,(ycoord)
ld a,h
or l
ret z

dec hl
ld (ycoord),hl
ret
;;---------------------------------------------------------------------------------------

move_down:
ld hl,(ycoord)
ld bc,scr_height-16
or a
sbc hl,bc
ret p

ld hl,(ycoord)
inc hl
ld (ycoord),hl
ret
;;---------------------------------------------------------------------------------------


;; init shift tables
;;
;; there are 7 tables for each of the possible shifts
;;
;; each table has a 16 bit number for each of the possible shift values
init_shift_table:
;; 256 bytes
ld b,0
;; initial byte
xor a

ist1:
push af
push bc
;; do 7 shifts

;; initial table
shift_table1:
ld d,0
ld e,a

;; number of shifts to do
ld c,7

;; this contains value shifted each time
ld h,a
ld l,0

ist2:
;; shift it
srl h
rr l

ld a,h
ld (de),a
inc d
ld a,l
ld (de),a
inc d

dec c
jr nz,ist2

pop bc
pop af
inc a
djnz ist1
ret
;;---------------------------------------------------------------------------------------


xcoord:
defw 0
ycoord:
defw 0
dimensions:
defb 16/8
defb 16
gfx:
defw sprite

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

draw_sprite:
ld hl,(xcoord)
ld de,(ycoord)
call get_scr_addr
ld bc,(dimensions)
defb &fd
ld l,c
defb &fd
ld h,b

ld de,(gfx)
ld a,(xcoord)
and 7
jp z,draw_masked_unshifted
dec a
add a,a                        ;; 2 bytes per table
shift_table2:
add a,0
ld b,a
jp draw_masked_shifted

;; IYH = height (in lines)
;; IYL = width (in bytes)
draw_masked_unshifted:

dmus:
push iy
push hl

dmur:
;; get mask
ld a,(de)
inc de
;; invert
cpl
;; combine with screen
and (hl)
;; and store
ld (hl),a

;; get pixels
ld a,(de)
inc de

;; combine with screen
or (hl)
;; and store
ld (hl),a
inc hl

defb &fd
dec l
jr nz,dmur

pop hl
call scr_next_line
pop iy

defb &fd
dec h
jr nz,dmus
ret


;; IYH = height (in lines)
;; IYL = width (in bytes)
;; B = shift table
draw_masked_shifted:

dmrs:
;; initialise previous shifted mask
defb &dd
ld h,0
;; initialise previous shifted data
defb &dd
ld l,0

push iy
push hl

dmr:

;; HL = screen address
;; DE = pixel data (mask, gfx)
;; B = preshift table

;; we need shifted mask for previous to combine with it
;; and we need shifted gfx for previous to combine with it

;; read unshifted mask
ld a,(de)
inc de

ld c,a
;; lookup shifted version (1st byte)
;; for this to work correctly, the mask needs to be inverted
ld a,(bc)

;; combine with previous shifted mask
defb &dd
or h

;; invert
cpl
;; isolate gfx from screen
and (hl)
;; store to screen
ld (hl),a

;; read next byte of shifted mask and store it
inc b
ld a,(bc)
defb &dd
ld h,a
dec b

;; read unshifted gfx
ld a,(de)
inc de
ld c,a
;; lookup shifted gfx
ld a,(bc)

;; combine with previous shifted data
defb &dd
or l

;; combine with screen
or (hl)
;; store to screen
ld (hl),a
inc hl

;; read next byte of shifted data and store it
inc b
ld a,(bc)
defb &dd
ld l,a
dec b

defb &fd
dec l
jr nz,dmr

;; we will have one byte remaining

;; do last column mask
defb &dd
ld a,h
cpl
and (hl)
ld (hl),a

;; do last column pixels
defb &dd
ld a,l
or (hl)
ld (hl),a

pop hl
call scr_next_line
pop iy

defb &fd
dec h
jp nz,dmrs
ret
;;---------------------------------------------------------------------------------------

;; input conditions:
;; HL = x byte coordinate (0-720)
;; DE = y coordinate (0-256)
;; output conditions:
;; HL = screen address

get_scr_addr:
push bc
srl h
rr l
srl h
rr l
srl h
rr l
ex de,hl
add hl,hl
ld bc,scr_table
add hl,bc
ld a,(hl)
inc hl
ld h,(hl)
ld l,a
add hl,de
pop bc
ret
;;---------------------------------------------------------------------------------------

scr_table:
defs scr_height*2
;;---------------------------------------------------------------------------------------


init_scr_addr_table:
ld ix,scr_table
scr_base:
ld hl,0
ld b,scr_height

gen_scr_table:
ld (ix+0),l
ld (ix+1),h
call scr_next_line
inc ix
inc ix
djnz gen_scr_table
ret
;;---------------------------------------------------------------------------------------

set_txt_coords:
;; H = x
;; L = y
ld a,l
add a,a
add a,a
add a,a
ld e,a
ld d,0
ld l,h
ld h,0
add hl,hl
add hl,hl
add hl,hl
call get_scr_addr
ld (txt_scr_addr),hl
ret
;;---------------------------------------------------------------------------------------

print_msg:
ld a,(hl)
inc hl
or a
ret z
call do_plot_char
jr print_msg
;;---------------------------------------------------------------------------------------

do_plot_char:
push af
push hl
push de
sub ' '
ld l,a
ld h,0
add hl,hl
add hl,hl
add hl,hl
ld de,font
add hl,de
ex de,hl
ld hl,(txt_scr_addr)
call plot_char
ld hl,(txt_scr_addr)
inc hl
ld (txt_scr_addr),hl
pop de
pop hl
pop af
ret
;;---------------------------------------------------------------------------------------

txt_scr_addr:
defw 0
;;---------------------------------------------------------------------------------------

plot_char:
push de
push hl
push bc
push af
ld b,8
pltchr:
ld a,(de)
ld (hl),a
inc de
call scr_next_line
djnz pltchr
pop af
pop bc
pop hl
pop de
ret
;;---------------------------------------------------------------------------------------

scr_next_line:
ld a,l
add a,64
ld l,a
ld a,h
adc a,0
ld h,a
ret
;;---------------------------------------------------------------------------------------

sprite:
incbin "cursor.bin"
;;---------------------------------------------------------------------------------------

message:
defb "THIS IS A TEST MESSAGE",0
;;---------------------------------------------------------------------------------------

font:
incbin "font.bin"
;;---------------------------------------------------------------------------------------

;;end start

Binary data is attached.

I hook into the system interrupt in a similar way to the built in game. I access the screen directly and draw some text and some shapes.

Maybe it will be of use to somebody?
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Offline redbox

  • Supporter
  • 6128 Plus
  • *
  • Posts: 1.751
  • Country: gb
    • redbox
  • Liked: 326
  • Likes Given: 267
Re: nc200 game
« Reply #1 on: 20:34, 31 January 14 »
Ah sh*t, just sold mine...!

Can you post a screenshot?

Offline Bryce

  • The Hardware Guy.
  • Supporter
  • 6128 Plus
  • *
  • Posts: 11.326
  • Country: wf
  • It's not broken, it just hasn't been fixed yet.
    • index.php?action=treasury
  • Liked: 4008
  • Likes Given: 419
Re: nc200 game
« Reply #2 on: 15:52, 01 February 14 »
Ah sh*t, just sold mine...!

To me! :) Looking forward to giving it a go  :P

Bryce.

Edit: Unfortunately the disk drive isn't working :( The lower head is missing a chunk. Looks like I'm going to have to source a new one. If anyone has one they'd like to part with, then let me know.
« Last Edit: 16:47, 01 February 14 by Bryce »

Offline arnoldemu

  • Supporter
  • 6128 Plus
  • *
  • Posts: 5.335
  • Country: gb
    • Unofficial Amstrad WWW Resource
  • Liked: 2261
  • Likes Given: 3478
Re: nc200 game
« Reply #3 on: 14:01, 02 February 14 »
Ah sh*t, just sold mine...!

Can you post a screenshot?
There isn't a game. I only wrote some code for drawing sprites and text and control movement with the keys.
Sorry if you thought there was a real game.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Offline Gryzor

  • Administrator
  • 6128 Plus
  • *****
  • Posts: 15.456
  • Country: gr
  • CPC-Wiki maintainer
    • CPCWiki
  • Liked: 3084
  • Likes Given: 5678
Re: nc200 game
« Reply #4 on: 19:19, 02 February 14 »
Damn, I got all excited and started thinking where I've stored my NC :D